1 29 30 package com.caucho.quercus.lib; 31 32 import com.caucho.quercus.QuercusModuleException; 33 import com.caucho.quercus.annotation.Optional; 34 import com.caucho.quercus.env.*; 35 import com.caucho.quercus.lib.file.FileModule; 36 import com.caucho.quercus.module.AbstractQuercusModule; 37 import com.caucho.util.IntMap; 38 import com.caucho.util.L10N; 39 import com.caucho.vfs.WriteStream; 40 41 import java.io.IOException ; 42 import java.util.HashMap ; 43 import java.util.Map ; 44 import java.util.logging.Logger ; 45 46 49 public class TokenModule extends AbstractQuercusModule { 50 private static final L10N L = new L10N(TokenModule.class); 51 private static final Logger log 52 = Logger.getLogger(TokenModule.class.getName()); 53 54 public static final int T_ABSTRACT = 256; 55 public static final int T_AND_EQUAL = 257; 56 public static final int T_ARRAY = 258; 57 public static final int T_ARRAY_CAST = 259; 58 public static final int T_AS = 260; 59 public static final int T_BAD_CHARACTER = 261; 60 public static final int T_BOOLEAN_AND = 262; 61 public static final int T_BOOLEAN_OR = 263; 62 public static final int T_BOOL_CAST = 264; 63 public static final int T_BREAK = 265; 64 public static final int T_CASE = 266; 65 public static final int T_CATCH = 267; 66 public static final int T_CHARACTER = 268; 67 public static final int T_CLASS = 269; 68 public static final int T_CLONE = 270; 69 public static final int T_CLOSE_TAG = 271; 70 public static final int T_COMMENT = 272; 71 public static final int T_CONCAT_EQUAL = 273; 72 public static final int T_CONST = 274; 73 public static final int T_CONSTANT_ENCAPSED_STRING = 275; 74 public static final int T_CONTINUE = 276; 75 public static final int T_CURLY_OPEN = 277; 76 public static final int T_DEC = 278; 77 public static final int T_DECLARE = 279; 78 public static final int T_DEFAULT = 280; 79 public static final int T_DIV_EQUAL = 281; 80 public static final int T_DNUMBER = 282; 81 public static final int T_DOC_COMMENT = 283; 82 public static final int T_DO = 284; 83 public static final int T_DOLLAR_OPEN_CURLY_BRACES = 285; 84 public static final int T_DOUBLE_ARROW = 286; 85 public static final int T_DOUBLE_CAST = 287; 86 public static final int T_DOUBLE_COLON = 288; 87 public static final int T_ECHO = 289; 88 public static final int T_ELSE = 290; 89 public static final int T_ELSEIF = 291; 90 public static final int T_EMPTY = 292; 91 public static final int T_ENCAPSED_AND_WHITESPACE = 293; 92 public static final int T_ENDDECLARE = 294; 93 public static final int T_ENDFOR = 295; 94 public static final int T_ENDFOREACH = 296; 95 public static final int T_ENDIF = 297; 96 public static final int T_ENDSWITCH = 298; 97 public static final int T_ENDWHILE = 299; 98 public static final int T_END_HEREDOC = 300; 99 public static final int T_EVAL = 301; 100 public static final int T_EXIT = 302; 101 public static final int T_EXTENDS = 303; 102 public static final int T_FILE = 304; 103 public static final int T_FINAL = 305; 104 public static final int T_FOR = 306; 105 public static final int T_FOREACH = 307; 106 public static final int T_FUNCTION = 308; 107 public static final int T_GLOBAL = 309; 108 public static final int T_HALT_COMPILER = 310; 109 public static final int T_IF = 311; 110 public static final int T_IMPLEMENTS = 312; 111 public static final int T_INC = 313; 112 public static final int T_INCLUDE = 314; 113 public static final int T_INCLUDE_ONCE = 315; 114 public static final int T_INLINE_HTML = 316; 115 public static final int T_INSTANCEOF = 317; 116 public static final int T_INT_CAST = 318; 117 public static final int T_INTERFACE = 319; 118 public static final int T_ISSET = 320; 119 public static final int T_IS_EQUAL = 321; 120 public static final int T_IS_GREATER_OR_EQUAL = 322; 121 public static final int T_IS_IDENTICAL = 323; 122 public static final int T_IS_NOT_EQUAL = 324; 123 public static final int T_IS_NOT_IDENTICAL = 325; 124 public static final int T_IS_SMALLER_OR_EQUAL = 326; 125 public static final int T_LINE = 327; 126 public static final int T_LIST = 328; 127 public static final int T_LNUMBER = 329; 128 public static final int T_LOGICAL_AND = 330; 129 public static final int T_LOGICAL_OR = 331; 130 public static final int T_LOGICAL_XOR = 332; 131 public static final int T_MINUS_EQUAL = 333; 132 public static final int T_ML_COMMENT = 334; 133 public static final int T_MOD_EQUAL = 335; 134 public static final int T_MUL_EQUAL = 336; 135 public static final int T_NEW = 337; 136 public static final int T_NUM_STRING = 338; 137 public static final int T_OBJECT_CAST = 339; 138 public static final int T_OBJECT_OPERATOR = 340; 139 public static final int T_OLD_FUNCTION = 341; 140 public static final int T_OPEN_TAG = 342; 141 public static final int T_OPEN_TAG_WITH_ECHO = 343; 142 public static final int T_OR_EQUAL = 344; 143 public static final int T_PAAMAYIM_NEKUDOTAYIM = T_DOUBLE_COLON; 144 public static final int T_PLUS_EQUAL = 345; 145 public static final int T_PRINT = 346; 146 public static final int T_PRIVATE = 347; 147 public static final int T_PUBLIC = 348; 148 public static final int T_PROTECTED = 349; 149 public static final int T_REQUIRE = 350; 150 public static final int T_REQUIRE_ONCE = 351; 151 public static final int T_RETURN = 352; 152 public static final int T_SL = 353; 153 public static final int T_SL_EQUAL = 354; 154 public static final int T_SR = 355; 155 public static final int T_SR_EQUAL = 356; 156 public static final int T_START_HEREDOC = 357; 157 public static final int T_STATIC = 358; 158 public static final int T_STRING = 359; 159 public static final int T_STRING_CAST = 360; 160 public static final int T_STRING_VARNAME = 361; 161 public static final int T_SWITCH = 362; 162 public static final int T_THROW = 363; 163 public static final int T_TRY = 364; 164 public static final int T_UNSET = 365; 165 public static final int T_UNSET_CAST = 366; 166 public static final int T_USE = 367; 167 public static final int T_VAR = 368; 168 public static final int T_VARIABLE = 369; 169 public static final int T_WHILE = 370; 170 public static final int T_WHITESPACE = 371; 171 public static final int T_XOR_EQUAL = 372; 172 public static final int T_FUNC_C = 373; 173 public static final int T_CLASS_C = 374; 174 175 private static final IntMap _reservedMap = new IntMap(); 176 177 private static final HashMap <String ,StringValue> _iniMap 178 = new HashMap <String ,StringValue>(); 179 180 public String []getLoadedExtensions() 181 { 182 return new String [] { "tokenizer" }; 183 } 184 185 188 public Map<String ,StringValue> getDefaultIni() 189 { 190 return _iniMap; 191 } 192 193 public static Value highlight_file(Env env, 194 String filename, 195 @Optional boolean isReturn) 196 { 197 StringValue v = FileModule.file_get_contents(env, 198 filename, 199 false, 200 null, 201 0, 202 Integer.MAX_VALUE); 203 204 if (v == null) 205 return BooleanValue.FALSE; 206 207 return highlight_string(env, v, isReturn); 208 } 209 210 public static Value highlight_string(Env env, 211 StringValue s, 212 @Optional boolean isReturn) 213 { 214 try { 215 StringBuilderValue sb = isReturn ? new StringBuilderValue() : null; 216 WriteStream out = env.getOut(); 217 218 Token lexer = new Token(s); 219 int token; 220 StringValue topColor = new StringValueImpl("#000000"); 221 StringValue lastColor = topColor; 222 223 highlight(sb, out, "<code>"); 224 highlight(sb, out, "<span style=\"color: #000000\">\n"); 225 226 while ((token = lexer.nextToken()) >= 0) { 227 StringValue color = getColor(env, token); 228 229 if (color != null && ! color.equals(lastColor)) { 230 if (! topColor.equals(lastColor)) 231 highlight(sb, out, "</span>"); 232 233 if (! topColor.equals(color)) 234 highlight(sb, out, "<span style=\"color: " + color + "\">"); 235 236 lastColor = color; 237 } 238 239 if (0x20 <= token && token <= 0x7f) { 240 if (sb != null) 241 sb.append((char) token); 242 else 243 out.print((char) token); 244 } 245 else { 246 StringValue lexeme = lexer.getLexeme(); 247 248 highlight(sb, out, lexeme); 249 } 250 } 251 252 if (! topColor.equals(lastColor)) 253 highlight(sb, out, "</span>\n"); 254 highlight(sb, out, "</span>\n"); 255 highlight(sb, out, "</code>"); 256 257 if (sb != null) 258 return sb; 259 else 260 return BooleanValue.TRUE; 261 } catch (IOException e) { 262 throw new QuercusModuleException(e); 263 } 264 } 265 266 private static void highlight(StringBuilderValue sb, 267 WriteStream out, 268 String string) 269 throws IOException 270 { 271 if (sb != null) { 272 sb.append(string); 273 } 274 else { 275 out.print(string); 276 } 277 } 278 279 private static void highlight(StringBuilderValue sb, 280 WriteStream out, 281 StringValue string) 282 throws IOException 283 { 284 if (sb != null) { 285 int len = string.length(); 286 for (int i = 0; i < len; i++) { 287 char ch = string.charAt(i); 288 289 switch (ch) { 290 case '<': 291 sb.append("<"); 292 break; 293 case '>': 294 sb.append(">"); 295 break; 296 default: 297 sb.append(ch); 298 break; 299 } 300 } 301 } 302 else { 303 int len = string.length(); 304 for (int i = 0; i < len; i++) { 305 char ch = string.charAt(i); 306 307 switch (ch) { 308 case '<': 309 out.print("<"); 310 break; 311 case '>': 312 out.print(">"); 313 break; 314 default: 315 out.print(ch); 316 break; 317 } 318 } 319 } 320 } 321 322 private static StringValue getColor(Env env, int token) 323 { 324 switch (token) { 325 case T_INLINE_HTML: 326 return env.getIni("highlight.html"); 327 328 case T_BAD_CHARACTER: 329 case T_CHARACTER: 330 case T_CLOSE_TAG: 331 case T_DNUMBER: 332 case T_END_HEREDOC: 333 case T_FILE: 334 case T_LINE: 335 case T_LNUMBER: 336 case T_OPEN_TAG: 337 case T_OPEN_TAG_WITH_ECHO: 338 return env.getIni("highlight.default"); 339 340 case T_COMMENT: 341 case T_DOC_COMMENT: 342 case T_ML_COMMENT: 343 return env.getIni("highlight.comment"); 344 345 case T_CONSTANT_ENCAPSED_STRING: 346 case T_STRING: 347 return env.getIni("highlight.string"); 348 349 case T_ENCAPSED_AND_WHITESPACE: 350 case T_WHITESPACE: 351 return null; 352 353 default: 354 return env.getIni("highlight.keyword"); 355 } 356 } 357 358 361 public static ArrayValue token_get_all(StringValue s) 362 { 363 ArrayValue result = new ArrayValueImpl(); 364 365 Token lexer = new Token(s); 366 int token; 367 368 while ((token = lexer.nextToken()) >= 0) { 369 if (0x20 <= token && token <= 0x7f) { 370 result.put(StringValue.create((char) token)); 371 } 372 else { 373 result.put(new ArrayValueImpl() 374 .append(LongValue.create(token)) 375 .append(lexer.getLexeme())); 376 } 377 } 378 379 return result; 380 } 381 382 385 public static String token_name(int token) 386 { 387 switch (token) { 388 case T_ABSTRACT: return "T_ABSTRACT"; 389 case T_AND_EQUAL: return "T_AND_EQUAL"; 390 case T_ARRAY: return "T_ARRAY"; 391 case T_ARRAY_CAST: return "T_ARRAY_CAST"; 392 case T_AS: return "T_AS"; 393 case T_BAD_CHARACTER: return "T_BAD_CHARACTER"; 394 case T_BOOLEAN_AND: return "T_BOOLEAN_AND"; 395 case T_BOOLEAN_OR: return "T_BOOLEAN_OR"; 396 case T_BOOL_CAST: return "T_BOOL_CAST"; 397 case T_BREAK: return "T_BREAK"; 398 case T_CASE: return "T_CASE"; 399 case T_CATCH: return "T_CATCH"; 400 case T_CHARACTER: return "T_CHARACTER"; 401 case T_CLASS: return "T_CLASS"; 402 case T_CLONE: return "T_CLONE"; 403 case T_CLOSE_TAG: return "T_CLOSE_TAG"; 404 case T_COMMENT: return "T_COMMENT"; 405 case T_CONCAT_EQUAL: return "T_CONCAT_EQUAL"; 406 case T_CONST: return "T_CONST"; 407 case T_CONSTANT_ENCAPSED_STRING: return "T_CONSTANT_ENCAPSED_STRING"; 408 case T_CONTINUE: return "T_CONTINUE"; 409 case T_CURLY_OPEN: return "T_CURLY_OPEN"; 410 case T_DEC: return "T_DEC"; 411 case T_DECLARE: return "T_DECLARE"; 412 case T_DEFAULT: return "T_DEFAULT"; 413 case T_DIV_EQUAL: return "T_DIV_EQUAL"; 414 case T_DNUMBER: return "T_DNUMBER"; 415 case T_DOC_COMMENT: return "T_DOC_COMMENT"; 416 case T_DO: return "T_DO"; 417 case T_DOLLAR_OPEN_CURLY_BRACES: return "T_DOLLAR_OPEN_CURLY_BRACES"; 418 case T_DOUBLE_ARROW: return "T_DOUBLE_ARROW"; 419 case T_DOUBLE_CAST: return "T_DOUBLE_CAST"; 420 case T_DOUBLE_COLON: return "T_DOUBLE_COLON"; 421 case T_ECHO: return "T_ECHO"; 422 case T_ELSE: return "T_ELSE"; 423 case T_ELSEIF: return "T_ELSEIF"; 424 case T_EMPTY: return "T_EMPTY"; 425 case T_ENCAPSED_AND_WHITESPACE: return "T_ENCAPSED_AND_WHITESPACE"; 426 case T_ENDDECLARE: return "T_ENDDECLARE"; 427 case T_ENDFOR: return "T_ENDFOR"; 428 case T_ENDFOREACH: return "T_ENDFOREACH"; 429 case T_ENDIF: return "T_ENDIF"; 430 case T_ENDSWITCH: return "T_ENDSWITCH"; 431 case T_ENDWHILE: return "T_ENDWHILE"; 432 case T_END_HEREDOC: return "T_END_HEREDOC"; 433 case T_EVAL: return "T_EVAL"; 434 case T_EXIT: return "T_EXIT"; 435 case T_EXTENDS: return "T_EXTENDS"; 436 case T_FILE: return "T_FILE"; 437 case T_FINAL: return "T_FINAL"; 438 case T_FOR: return "T_FOR"; 439 case T_FOREACH: return "T_FOREACH"; 440 case T_FUNCTION: return "T_FUNCTION"; 441 case T_GLOBAL: return "T_GLOBAL"; 442 case T_HALT_COMPILER: return "T_HALT_COMPILER"; 443 case T_IF: return "T_IF"; 444 case T_IMPLEMENTS: return "T_IMPLEMENTS"; 445 case T_INC: return "T_INC"; 446 case T_INCLUDE: return "T_INCLUDE"; 447 case T_INCLUDE_ONCE: return "T_INCLUDE_ONCE"; 448 case T_INLINE_HTML: return "T_INLINE_HTML"; 449 case T_INSTANCEOF: return "T_INSTANCEOF"; 450 case T_INT_CAST: return "T_INT_CAST"; 451 case T_INTERFACE: return "T_INTERFACE"; 452 case T_ISSET: return "T_ISSET"; 453 case T_IS_EQUAL: return "T_IS_EQUAL"; 454 case T_IS_GREATER_OR_EQUAL: return "T_IS_GREATER_OR_EQUAL"; 455 case T_IS_IDENTICAL: return "T_IS_IDENTICAL"; 456 case T_IS_NOT_EQUAL: return "T_IS_NOT_EQUAL"; 457 case T_IS_NOT_IDENTICAL: return "T_IS_NOT_IDENTICAL"; 458 case T_IS_SMALLER_OR_EQUAL: return "T_IS_SMALLER_OR_EQUAL"; 459 case T_LINE: return "T_LINE"; 460 case T_LIST: return "T_LIST"; 461 case T_LNUMBER: return "T_LNUMBER"; 462 case T_LOGICAL_AND: return "T_LOGICAL_AND"; 463 case T_LOGICAL_OR: return "T_LOGICAL_OR"; 464 case T_LOGICAL_XOR: return "T_LOGICAL_XOR"; 465 case T_MINUS_EQUAL: return "T_MINUS_EQUAL"; 466 case T_ML_COMMENT: return "T_ML_COMMENT"; 467 case T_MOD_EQUAL: return "T_MOD_EQUAL"; 468 case T_MUL_EQUAL: return "T_MUL_EQUAL"; 469 case T_NEW: return "T_NEW"; 470 case T_NUM_STRING: return "T_NUM_STRING"; 471 case T_OBJECT_CAST: return "T_OBJECT_CAST"; 472 case T_OBJECT_OPERATOR: return "T_OBJECT_OPERATOR"; 473 case T_OLD_FUNCTION: return "T_OLD_FUNCTION"; 474 case T_OPEN_TAG: return "T_OPEN_TAG"; 475 case T_OPEN_TAG_WITH_ECHO: return "T_OPEN_TAG_WITH_ECHO"; 476 case T_OR_EQUAL: return "T_OR_EQUAL"; 477 case T_PLUS_EQUAL: return "T_PLUS_EQUAL"; 478 case T_PRINT: return "T_PRINT"; 479 case T_PRIVATE: return "T_PRIVATE"; 480 case T_PUBLIC: return "T_PUBLIC"; 481 case T_PROTECTED: return "T_PROTECTED"; 482 case T_REQUIRE: return "T_REQUIRE"; 483 case T_REQUIRE_ONCE: return "T_REQUIRE_ONCE"; 484 case T_RETURN: return "T_RETURN"; 485 case T_SL: return "T_SL"; 486 case T_SL_EQUAL: return "T_SL_EQUAL"; 487 case T_SR: return "T_SR"; 488 case T_SR_EQUAL: return "T_SR_EQUAL"; 489 case T_START_HEREDOC: return "T_START_HEREDOC"; 490 case T_STATIC: return "T_STATIC"; 491 case T_STRING: return "T_STRING"; 492 case T_STRING_CAST: return "T_STRING_CAST"; 493 case T_STRING_VARNAME: return "T_STRING_VARNAME"; 494 case T_SWITCH: return "T_SWITCH"; 495 case T_THROW: return "T_THROW"; 496 case T_TRY: return "T_TRY"; 497 case T_UNSET: return "T_UNSET"; 498 case T_UNSET_CAST: return "T_UNSET_CAST"; 499 case T_USE: return "T_USE"; 500 case T_VAR: return "T_VAR"; 501 case T_VARIABLE: return "T_VARIABLE"; 502 case T_WHILE: return "T_WHILE"; 503 case T_WHITESPACE: return "T_WHITESPACE"; 504 case T_XOR_EQUAL: return "T_XOR_EQUAL"; 505 case T_FUNC_C: return "T_FUNC_C"; 506 case T_CLASS_C: return "T_CLASS_C"; 507 508 default: 509 return "UNDEFINED"; 510 } 511 } 512 513 static class Token { 514 private final StringValue _s; 515 private final int _length; 516 private int _i; 517 private boolean _inPhp; 518 519 private StringBuilderValue _lexeme; 520 521 Token(StringValue s) 522 { 523 _s = s; 524 _length = s.length(); 525 } 526 527 int nextToken() 528 { 529 _lexeme = new StringBuilderValue(); 530 531 if (! _inPhp) { 532 _inPhp = true; 533 534 if (parseHtml()) { 535 return T_INLINE_HTML; 536 } 537 } 538 539 int ch = read(); 540 541 switch (ch) { 542 case -1: 543 return -1; 544 545 case ' ': case '\t': case '\r': case '\n': 546 _lexeme.append((char) ch); 547 while (Character.isWhitespace((ch = read()))) { 548 _lexeme.append((char) ch); 549 } 550 unread(); 551 return T_WHITESPACE; 552 553 case '{': case '}': case ';': case '[': case ']': case ',': 554 case '@': case '(': case ')': 555 return ch; 556 557 case '&': 558 if ((ch = read()) == '&') { 559 _lexeme.append("&&"); 560 return T_BOOLEAN_AND; 561 } 562 else if (ch == '=') { 563 _lexeme.append("&="); 564 return T_AND_EQUAL; 565 } 566 else { 567 unread(); 568 return '&'; 569 } 570 571 case '|': 572 if ((ch = read()) == '|') { 573 _lexeme.append("||"); 574 return T_BOOLEAN_OR; 575 } 576 else if (ch == '=') { 577 _lexeme.append("|="); 578 return T_OR_EQUAL; 579 } 580 else { 581 unread(); 582 return '|'; 583 } 584 585 case '?': 586 if ((ch = read()) == '>') { 587 _lexeme.append("?>"); 588 _inPhp = false; 589 return T_CLOSE_TAG; 590 } 591 else { 592 unread(); 593 return '?'; 594 } 595 596 case '/': 597 if ((ch = read()) == '/') { 598 _lexeme.append("//"); 599 600 while ((ch = read()) >= 0 && ch != '\r' && ch != '\n') { 601 _lexeme.append((char) ch); 602 } 603 unread(); 604 605 return T_COMMENT; 606 } 607 else if (ch == '=') { 608 _lexeme.append("/="); 609 return T_DIV_EQUAL; 610 } 611 else if (ch == '*') { 612 int token = T_COMMENT; 613 _lexeme.append("/*"); 614 615 if ((ch = read()) == '*') { 616 token = T_DOC_COMMENT; 617 _lexeme.append("*"); 618 } 619 else 620 unread(); 621 622 while ((ch = read()) >= 0) { 623 _lexeme.append((char) ch); 624 625 if (ch != '*') { 626 } 627 else if ((ch = read()) == '/') { 628 _lexeme.append((char) ch); 629 return token; 630 } 631 else 632 unread(); 633 } 634 635 return token; 636 } 637 else { 638 unread(); 639 return '/'; 640 } 641 642 case '#': 643 _lexeme.append((char) '#'); 644 while ((ch = read()) >= 0 && ch != '\r' && ch != '\n') { 645 _lexeme.append((char) ch); 646 } 647 unread(); 648 return T_COMMENT; 649 650 case '.': 651 if ((ch = read()) == '=') { 652 _lexeme.append(".="); 653 return T_CONCAT_EQUAL; 654 } 655 else { 656 unread(); 657 return '.'; 658 } 659 660 case '\'': case '"': case '`': 661 { 662 int end = ch; 663 664 _lexeme.append((char) ch); 665 666 while ((ch = read()) >= 0 && ch != end) { 667 _lexeme.append((char) ch); 668 669 if (ch == '\\') { 670 _lexeme.append((char) read()); 671 } 672 } 673 674 if (ch > 0) 675 _lexeme.append((char) ch); 676 677 return T_CONSTANT_ENCAPSED_STRING; 678 } 679 680 case '-': 681 if ((ch = read()) == '-') { 682 _lexeme.append("--"); 683 return T_DEC; 684 } 685 else if (ch == '=') { 686 _lexeme.append("-="); 687 return T_MINUS_EQUAL; 688 } 689 else if (ch == '>') { 690 _lexeme.append("->"); 691 return T_OBJECT_OPERATOR; 692 } 693 else { 694 unread(); 695 return '-'; 696 } 697 698 case '+': 699 if ((ch = read()) == '+') { 700 _lexeme.append("++"); 701 return T_INC; 702 } 703 else if (ch == '=') { 704 _lexeme.append("+="); 705 return T_PLUS_EQUAL; 706 } 707 else { 708 unread(); 709 return '+'; 710 } 711 712 case '>': 713 if ((ch = read()) == '>') { 714 if ((ch = read()) == '=') { 715 _lexeme.append(">>="); 716 return T_SR_EQUAL; 717 } 718 else { 719 unread(); 720 _lexeme.append(">>"); 721 return T_SR; 722 } 723 } 724 else if (ch == '=') { 725 _lexeme.append(">="); 726 return T_IS_GREATER_OR_EQUAL; 727 } 728 else { 729 unread(); 730 return '>'; 731 } 732 733 case '$': 734 if ((ch = read()) == '{') { 735 _lexeme.append("${"); 736 return T_DOLLAR_OPEN_CURLY_BRACES; 737 } 738 else if (ch == '$') { 739 unread(); 740 return '$'; 741 } 742 else if (Character.isJavaIdentifierStart(ch)) { 743 unread(); 744 _lexeme.append("$"); 745 readIdentifier(); 746 return T_VARIABLE; 747 } 748 else { 749 unread(); 750 return '$'; 751 } 752 753 case '=': 754 if ((ch = read()) == '=') { 755 if ((ch = read()) == '=') { 756 _lexeme.append("==="); 757 return T_IS_IDENTICAL; 758 } 759 else { 760 unread(); 761 _lexeme.append("=="); 762 return T_IS_EQUAL; 763 } 764 } 765 else if (ch == '>') { 766 _lexeme.append("=>"); 767 return T_DOUBLE_ARROW; 768 } 769 else { 770 unread(); 771 return '='; 772 } 773 774 case '!': 775 if ((ch = read()) == '=') { 776 if ((ch = read()) == '=') { 777 _lexeme.append("!=="); 778 return T_IS_NOT_IDENTICAL; 779 } 780 else { 781 unread(); 782 _lexeme.append("!="); 783 return T_IS_NOT_EQUAL; 784 } 785 } 786 else { 787 unread(); 788 return '!'; 789 } 790 791 case ':': 792 if ((ch = read()) == ':') { 793 _lexeme.append("::"); 794 return T_DOUBLE_COLON; 795 } 796 else { 797 unread(); 798 return ':'; 799 } 800 801 case '<': 802 if ((ch = read()) == '?') { 803 if ((ch = read()) == '=') { 804 _lexeme.append("<?="); 805 return T_OPEN_TAG_WITH_ECHO; 806 } 807 else if (ch != 'p') { 808 unread(); 809 _lexeme.append("<?"); 810 return T_OPEN_TAG; 811 } 812 else if ((ch = read()) != 'h') { 813 unread(); 814 unread(); 815 _lexeme.append("<?"); 816 return T_OPEN_TAG; 817 } 818 else if ((ch = read()) != 'p') { 819 unread(); 820 unread(); 821 unread(); 822 _lexeme.append("<?"); 823 return T_OPEN_TAG; 824 } 825 else { 826 _lexeme.append("<?php"); 827 return T_OPEN_TAG; 828 } 829 } 830 else if (ch == '%') { 831 if ((ch = read()) == '=') { 832 _lexeme.append("<%="); 833 return T_OPEN_TAG_WITH_ECHO; 834 } 835 else { 836 unread(); 837 _lexeme.append("<%"); 838 return T_OPEN_TAG; 839 } 840 } 841 else if (ch == '<') { 842 if ((ch = read()) == '=') { 843 _lexeme.append("<<="); 844 return T_SL_EQUAL; 845 } 846 else if (ch == '<') { 847 _lexeme.append("<<<"); 848 return T_START_HEREDOC; 849 } 850 else { 851 unread(); 852 _lexeme.append("<<"); 853 return T_SL; 854 } 855 } 856 else if (ch == '=') { 857 _lexeme.append("<="); 858 return T_IS_SMALLER_OR_EQUAL; 859 } 860 else if (ch == '>') { 861 _lexeme.append("<>"); 862 return T_IS_NOT_EQUAL; 863 } 864 else { 865 unread(); 866 return '<'; 867 } 868 869 case '*': 870 if ((ch = read()) == '=') { 871 _lexeme.append("*="); 872 return T_MUL_EQUAL; 873 } 874 else { 875 unread(); 876 return '*'; 877 } 878 879 case '%': 880 if ((ch = read()) == '=') { 881 _lexeme.append("%="); 882 return T_MOD_EQUAL; 883 } 884 else { 885 unread(); 886 return '%'; 887 } 888 889 case '^': 890 if ((ch = read()) == '=') { 891 _lexeme.append("^="); 892 return T_XOR_EQUAL; 893 } 894 else { 895 unread(); 896 return '^'; 897 } 898 899 case '0': case '1': case '2': case '3': case '4': 900 case '5': case '6': case '7': case '8': case '9': 901 unread(); 902 return parseNumber(); 903 904 default: 905 if (Character.isJavaIdentifierStart(ch)) { 906 unread(); 907 908 readIdentifier(); 909 910 int lexeme = _reservedMap.get(_lexeme.toString().toLowerCase()); 911 912 if (lexeme > 0) 913 return lexeme; 914 915 return T_STRING; 916 } 917 918 _lexeme.append((char) ch); 919 return T_BAD_CHARACTER; 920 } 921 } 922 923 StringBuilderValue getLexeme() 924 { 925 return _lexeme; 926 } 927 928 private boolean parseHtml() 929 { 930 int ch; 931 932 while ((ch = read()) >= 0) { 933 if (ch != '<') 934 _lexeme.append((char) ch); 935 else if ((ch = read()) == '?' || ch == '%') { 936 unread(); 937 unread(); 938 939 return _lexeme.length() > 0; 940 } 941 else { 942 _lexeme.append((char) '<'); 943 944 unread(); 945 } 946 } 947 948 return _lexeme.length() > 0; 949 } 950 951 private void readIdentifier() 952 { 953 int ch; 954 955 while (Character.isJavaIdentifierPart((ch = read()))) { 956 _lexeme.append((char) ch); 957 } 958 959 unread(); 960 } 961 962 private int parseNumber() 963 { 964 boolean isInt = false; 965 int ch; 966 967 while ('0' <= (ch = read()) && ch <= '9' 968 || ch == '.' 969 || ch == 'x' || ch == 'X' 970 || 'a' <= ch && ch <= 'f' 971 || 'A' <= ch && ch <= 'F') { 972 _lexeme.append((char) ch); 973 974 if ('a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'f' 975 || ch == 'x' || ch == 'X') 976 isInt = true; 977 } 978 979 unread(); 980 981 return T_LNUMBER; 982 } 983 984 private int read() 985 { 986 if (_i < _length) 987 return _s.charAt(_i++); 988 else { 989 _i++; 990 return -1; 991 } 992 } 993 994 private void unread() 995 { 996 if (_i <= _length) 997 _i--; 998 } 999 } 1000 1001 static { 1002 _reservedMap.put("abstract", T_ABSTRACT); 1003 _reservedMap.put("array", T_ARRAY); 1004 _reservedMap.put("as", T_AS); 1005 _reservedMap.put("break", T_BREAK); 1006 _reservedMap.put("case", T_CASE); 1007 _reservedMap.put("catch", T_CATCH); 1008 _reservedMap.put("class", T_CLASS); 1009 _reservedMap.put("clone", T_CLONE); 1010 _reservedMap.put("const", T_CONST); 1011 _reservedMap.put("continue", T_CONTINUE); 1012 _reservedMap.put("declare", T_DECLARE); 1013 _reservedMap.put("default", T_DEFAULT); 1014 _reservedMap.put("do", T_DO); 1015 _reservedMap.put("echo", T_ECHO); 1016 _reservedMap.put("else", T_ELSE); 1017 _reservedMap.put("elseif", T_ELSEIF); 1018 _reservedMap.put("empty", T_EMPTY); 1019 _reservedMap.put("enddeclare", T_ENDDECLARE); 1020 _reservedMap.put("endfor", T_ENDFOR); 1021 _reservedMap.put("endforeach", T_ENDFOREACH); 1022 _reservedMap.put("endif", T_ENDIF); 1023 _reservedMap.put("endswitch", T_ENDSWITCH); 1024 _reservedMap.put("eval", T_EVAL); 1025 _reservedMap.put("exit", T_EXIT); 1026 _reservedMap.put("die", T_EXIT); 1027 _reservedMap.put("extends", T_EXTENDS); 1028 _reservedMap.put("__FILE__", T_FILE); 1029 _reservedMap.put("final", T_FINAL); 1030 _reservedMap.put("for", T_FOR); 1031 _reservedMap.put("foreach", T_FOREACH); 1032 _reservedMap.put("function", T_FUNCTION); 1033 _reservedMap.put("cfunction", T_FUNCTION); 1034 _reservedMap.put("global", T_GLOBAL); 1035 _reservedMap.put("__halt_compiler", T_HALT_COMPILER); 1036 _reservedMap.put("if", T_IF); 1037 _reservedMap.put("implements", T_IMPLEMENTS); 1038 _reservedMap.put("include", T_INCLUDE); 1039 _reservedMap.put("include_once", T_INCLUDE_ONCE); 1040 _reservedMap.put("instanceof", T_INSTANCEOF); 1041 _reservedMap.put("isset", T_ISSET); 1042 _reservedMap.put("list", T_LIST); 1043 _reservedMap.put("and", T_LOGICAL_AND); 1044 _reservedMap.put("or", T_LOGICAL_OR); 1045 _reservedMap.put("xor", T_LOGICAL_XOR); 1046 _reservedMap.put("new", T_NEW); 1047 _reservedMap.put("old_function", T_OLD_FUNCTION); 1048 _reservedMap.put("print", T_PRINT); 1049 _reservedMap.put("private", T_PRIVATE); 1050 _reservedMap.put("public", T_PUBLIC); 1051 _reservedMap.put("protected", T_PROTECTED); 1052 _reservedMap.put("require", T_REQUIRE); 1053 _reservedMap.put("require_once", T_REQUIRE_ONCE); 1054 _reservedMap.put("return", T_RETURN); 1055 _reservedMap.put("static", T_STATIC); 1056 _reservedMap.put("switch", T_SWITCH); 1057 _reservedMap.put("throw", T_THROW); 1058 _reservedMap.put("try", T_TRY); 1059 _reservedMap.put("unset", T_UNSET); 1060 _reservedMap.put("var", T_VAR); 1061 _reservedMap.put("while", T_WHILE); 1062 _reservedMap.put("__FUNCTION__", T_FUNC_C); 1063 _reservedMap.put("__CLASS__", T_CLASS_C); 1064 } 1065 1066 static { 1067 addIni(_iniMap, "highlight.string", "#DD0000", PHP_INI_ALL); 1068 addIni(_iniMap, "highlight.comment", "#FF8000", PHP_INI_ALL); 1069 addIni(_iniMap, "highlight.keyword", "#007700", PHP_INI_ALL); 1070 addIni(_iniMap, "highlight.bg", "#ffffff", PHP_INI_ALL); 1071 addIni(_iniMap, "highlight.default", "#0000BB", PHP_INI_ALL); 1072 addIni(_iniMap, "highlight.html", "#000000", PHP_INI_ALL); 1073 } 1074} 1075 | Popular Tags |