1 package org.jf.smali; 2 3 import java.io.*; 4 import org.antlr.runtime.*; 5 import org.jf.util.*; 6 import static org.jf.smali.smaliParser.*; 7 8 %% 9 10 %public 11 %class smaliFlexLexer 12 %implements TokenSource 13 %implements LexerErrorInterface 14 %type Token 15 %unicode 16 %line 17 %column 18 %char 19 20 %{ 21 private StringBuffer sb = new StringBuffer(); 22 private String stringOrCharError = null; 23 private int stringStartLine; 24 private int stringStartCol; 25 private int stringStartChar; 26 27 private int lexerErrors = 0; 28 29 private File sourceFile; 30 31 private boolean suppressErrors; 32 33 public Token nextToken() { 34 try { 35 Token token = yylex(); 36 if (token instanceof InvalidToken) { 37 InvalidToken invalidToken = (InvalidToken)token; 38 if (!suppressErrors) { 39 System.err.println(getErrorHeader(invalidToken) + " Error for input '" + 40 invalidToken.getText() + "': " + invalidToken.getMessage()); 41 } 42 lexerErrors++; 43 } 44 return token; 45 } 46 catch (java.io.IOException e) { 47 System.err.println("shouldn't happen: " + e.getMessage()); 48 return Token.EOF_TOKEN; 49 } 50 } 51 52 public void setLine(int line) { 53 this.yyline = line-1; 54 } 55 56 public void setColumn(int column) { 57 this.yycolumn = column; 58 } 59 60 public int getLine() { 61 return this.yyline+1; 62 } 63 64 public int getColumn() { 65 return this.yycolumn; 66 } 67 68 public void setSuppressErrors(boolean suppressErrors) { 69 this.suppressErrors = suppressErrors; 70 } 71 72 public void setSourceFile(File sourceFile) { 73 this.sourceFile = sourceFile; 74 } 75 76 public String getSourceName() { 77 try { 78 return PathUtil.getRelativeFile(new File("."), sourceFile).getPath(); 79 } catch (IOException ex) { 80 return sourceFile.getAbsolutePath(); 81 } 82 } 83 84 public int getNumberOfSyntaxErrors() { 85 return lexerErrors; 86 } 87 88 private Token newToken(int type, String text, boolean hidden) { 89 CommonToken token = new CommonToken(type, text); 90 if (hidden) { 91 token.setChannel(Token.HIDDEN_CHANNEL); 92 } 93 94 token.setStartIndex(yychar); 95 token.setStopIndex(yychar + yylength() - 1); 96 token.setLine(getLine()); 97 token.setCharPositionInLine(getColumn()); 98 return token; 99 } 100 101 private Token newToken(int type, String text) { 102 return newToken(type, text, false); 103 } 104 105 private Token newToken(int type, boolean hidden) { 106 return newToken(type, yytext(), hidden); 107 } 108 109 private Token newToken(int type) { 110 return newToken(type, yytext(), false); 111 } 112 113 private Token invalidToken(String message, String text) { 114 InvalidToken token = new InvalidToken(message, text); 115 116 token.setStartIndex(yychar); 117 token.setStopIndex(yychar + yylength() - 1); 118 token.setLine(getLine()); 119 token.setCharPositionInLine(getColumn()); 120 121 return token; 122 } 123 124 private Token invalidToken(String message) { 125 return invalidToken(message, yytext()); 126 } 127 128 private void beginStringOrChar(int state) { 129 yybegin(state); 130 sb.setLength(0); 131 stringStartLine = getLine(); 132 stringStartCol = getColumn(); 133 stringStartChar = yychar; 134 stringOrCharError = null; 135 } 136 137 private Token endStringOrChar(int type) { 138 yybegin(YYINITIAL); 139 140 if (stringOrCharError != null) { 141 return invalidStringOrChar(stringOrCharError); 142 } 143 144 CommonToken token = new CommonToken(type, sb.toString()); 145 token.setStartIndex(stringStartChar); 146 token.setStopIndex(yychar + yylength() - 1); 147 token.setLine(stringStartLine); 148 token.setCharPositionInLine(stringStartCol); 149 return token; 150 } 151 152 private void setStringOrCharError(String message) { 153 if (stringOrCharError == null) { 154 stringOrCharError = message; 155 } 156 } 157 158 private Token invalidStringOrChar(String message) { 159 yybegin(YYINITIAL); 160 161 InvalidToken token = new InvalidToken(message, sb.toString()); 162 token.setStartIndex(stringStartChar); 163 token.setStopIndex(yychar + yylength() - 1); 164 token.setLine(stringStartLine); 165 token.setCharPositionInLine(stringStartCol); 166 return token; 167 } 168 169 public String getErrorHeader(InvalidToken token) { 170 return getSourceName()+"["+ token.getLine()+","+token.getCharPositionInLine()+"]"; 171 } 172 %} 173 174 HexPrefix = 0 [xX] 175 176 HexDigit = [0-9a-fA-F] 177 HexDigits = [0-9a-fA-F]{4} 178 FewerHexDigits = [0-9a-fA-F]{0,3} 179 180 Integer1 = 0 181 Integer2 = [1-9] [0-9]* 182 Integer3 = 0 [0-7]+ 183 Integer4 = {HexPrefix} {HexDigit}+ 184 Integer = {Integer1} | {Integer2} | {Integer3} | {Integer4} 185 186 DecimalExponent = [eE] -? [0-9]+ 187 188 BinaryExponent = [pP] -? [0-9]+ 189 190 /*This can either be a floating point number or an identifier*/ 191 FloatOrID1 = -? [0-9]+ {DecimalExponent} 192 FloatOrID2 = -? {HexPrefix} {HexDigit}+ {BinaryExponent} 193 FloatOrID3 = -? [iI][nN][fF][iI][nN][iI][tT][yY] 194 FloatOrID4 = [nN][aA][nN] 195 FloatOrID = {FloatOrID1} | {FloatOrID2} | {FloatOrID3} | {FloatOrID4} 196 197 198 /*This can only be a float and not an identifier, due to the decimal point*/ 199 Float1 = -? [0-9]+ "." [0-9]* {DecimalExponent}? 200 Float2 = -? "." [0-9]+ {DecimalExponent}? 201 Float3 = -? {HexPrefix} {HexDigit}+ "." {HexDigit}* {BinaryExponent} 202 Float4 = -? {HexPrefix} "." {HexDigit}+ {BinaryExponent} 203 Float = {Float1} | {Float2} | {Float3} | {Float4} 204 205 HighSurrogate = [\ud800-\udbff] 206 207 LowSurrogate = [\udc00-\udfff] 208 209 SimpleNameCharacter = ({HighSurrogate} {LowSurrogate}) | [A-Za-z0-9$\-_\u00a1-\u1fff\u2010-\u2027\u2030-\ud7ff\ue000-\uffef] 210 211 SimpleName = {SimpleNameCharacter}+ 212 213 PrimitiveType = [ZBSCIJFD] 214 215 ClassDescriptor = L ({SimpleName} "/")* {SimpleName} ; 216 217 ArrayDescriptor = "[" + ({PrimitiveType} | {ClassDescriptor}) 218 219 Type = {PrimitiveType} | {ClassDescriptor} | {ArrayDescriptor} 220 221 222 %state STRING 223 %state CHAR 224 225 %% 226 227 /*Directives*/ 228 <YYINITIAL> 229 { 230 ".class" { return newToken(CLASS_DIRECTIVE); } 231 ".super" { return newToken(SUPER_DIRECTIVE); } 232 ".implements" { return newToken(IMPLEMENTS_DIRECTIVE); } 233 ".source" { return newToken(SOURCE_DIRECTIVE); } 234 ".field" { return newToken(FIELD_DIRECTIVE); } 235 ".end field" { return newToken(END_FIELD_DIRECTIVE); } 236 ".subannotation" { return newToken(SUBANNOTATION_DIRECTIVE); } 237 ".end subannotation" { return newToken(END_SUBANNOTATION_DIRECTIVE); } 238 ".annotation" { return newToken(ANNOTATION_DIRECTIVE); } 239 ".end annotation" { return newToken(END_ANNOTATION_DIRECTIVE); } 240 ".enum" { return newToken(ENUM_DIRECTIVE); } 241 ".method" { return newToken(METHOD_DIRECTIVE); } 242 ".end method" { return newToken(END_METHOD_DIRECTIVE); } 243 ".registers" { return newToken(REGISTERS_DIRECTIVE); } 244 ".locals" { return newToken(LOCALS_DIRECTIVE); } 245 ".array-data" { return newToken(ARRAY_DATA_DIRECTIVE); } 246 ".end array-data" { return newToken(END_ARRAY_DATA_DIRECTIVE); } 247 ".packed-switch" { return newToken(PACKED_SWITCH_DIRECTIVE); } 248 ".end packed-switch" { return newToken(END_PACKED_SWITCH_DIRECTIVE); } 249 ".sparse-switch" { return newToken(SPARSE_SWITCH_DIRECTIVE); } 250 ".end sparse-switch" { return newToken(END_SPARSE_SWITCH_DIRECTIVE); } 251 ".catch" { return newToken(CATCH_DIRECTIVE); } 252 ".catchall" { return newToken(CATCHALL_DIRECTIVE); } 253 ".line" { return newToken(LINE_DIRECTIVE); } 254 ".parameter" { return newToken(PARAMETER_DIRECTIVE); } 255 ".end parameter" { return newToken(END_PARAMETER_DIRECTIVE); } 256 ".local" { return newToken(LOCAL_DIRECTIVE); } 257 ".end local" { return newToken(END_LOCAL_DIRECTIVE); } 258 ".restart local" { return newToken(RESTART_LOCAL_DIRECTIVE); } 259 ".prologue" { return newToken(PROLOGUE_DIRECTIVE); } 260 ".epilogue" { return newToken(EPILOGUE_DIRECTIVE); } 261 262 ".end" { return invalidToken("Invalid directive"); } 263 ".end " [a-zA-z0-9\-_]+ { return invalidToken("Invalid directive"); } 264 ".restart" { return invalidToken("Invalid directive"); } 265 ".restart " [a-zA-z0-9\-_]+ { return invalidToken("Invalid directive"); } 266 } 267 268 /*Literals*/ 269 <YYINITIAL> { 270 -? {Integer} { return newToken(INTEGER_LITERAL); } 271 -? {Integer} [lL] { return newToken(LONG_LITERAL); } 272 -? {Integer} [sS] { return newToken(SHORT_LITERAL); } 273 -? {Integer} [tT] { return newToken(BYTE_LITERAL); } 274 275 {FloatOrID} [fF] | -? [0-9]+ [fF] { return newToken(FLOAT_LITERAL_OR_ID); } 276 {FloatOrID} [dD]? | -? [0-9]+ [dD] { return newToken(DOUBLE_LITERAL_OR_ID); } 277 {Float} [fF] { return newToken(FLOAT_LITERAL); } 278 {Float} [dD]? { return newToken(DOUBLE_LITERAL); } 279 280 "true"|"false" { return newToken(BOOL_LITERAL); } 281 "null" { return newToken(NULL_LITERAL); } 282 283 "\"" { beginStringOrChar(STRING); sb.append('"'); } 284 285 ' { beginStringOrChar(CHAR); sb.append('\''); } 286 } 287 288 <STRING> { 289 "\"" { sb.append('"'); return endStringOrChar(STRING_LITERAL); } 290 291 [^\r\n\"\\]+ { sb.append(yytext()); } 292 "\\b" { sb.append('\b'); } 293 "\\t" { sb.append('\t'); } 294 "\\n" { sb.append('\n'); } 295 "\\f" { sb.append('\f'); } 296 "\\r" { sb.append('\r'); } 297 "\\'" { sb.append('\''); } 298 "\\\"" { sb.append('"'); } 299 "\\\\" { sb.append('\\'); } 300 "\\u" {HexDigits} { sb.append((char)Integer.parseInt(yytext().substring(2,6), 16)); } 301 302 "\\u" {FewerHexDigits} { 303 sb.append(yytext()); 304 setStringOrCharError("Invalid \\u sequence. \\u must be followed by 4 hex digits"); 305 } 306 307 "\\" [^btnfr'\"\\u] { 308 sb.append(yytext()); 309 setStringOrCharError("Invalid escape sequence " + yytext()); 310 } 311 312 [\r\n] { return invalidStringOrChar("Unterminated string literal"); } 313 <<EOF>> { return invalidStringOrChar("Unterminated string literal"); } 314 } 315 316 <CHAR> { 317 ' { 318 sb.append('\''); 319 if (sb.length() == 2) { 320 return invalidStringOrChar("Empty character literal"); 321 } else if (sb.length() > 3) { 322 return invalidStringOrChar("Character literal with multiple chars"); 323 } 324 325 return endStringOrChar(CHAR_LITERAL); 326 } 327 328 [^\r\n'\\]+ { sb.append(yytext()); } 329 "\\b" { sb.append('\b'); } 330 "\\t" { sb.append('\t'); } 331 "\\n" { sb.append('\n'); } 332 "\\f" { sb.append('\f'); } 333 "\\r" { sb.append('\r'); } 334 "\\'" { sb.append('\''); } 335 "\\\"" { sb.append('"'); } 336 "\\\\" { sb.append('\\'); } 337 "\\u" {HexDigits} { sb.append((char)Integer.parseInt(yytext().substring(2,6), 16)); } 338 339 "\\u" {HexDigit}* { 340 sb.append(yytext()); 341 setStringOrCharError("Invalid \\u sequence. \\u must be followed by exactly 4 hex digits"); 342 } 343 344 "\\" [^btnfr'\"\\u] { 345 sb.append(yytext()); 346 setStringOrCharError("Invalid escape sequence " + yytext()); 347 } 348 349 [\r\n] { return invalidStringOrChar("Unterminated character literal"); } 350 <<EOF>> { return invalidStringOrChar("Unterminated character literal"); } 351 } 352 353 /*Misc*/ 354 <YYINITIAL> { 355 [vp] [0-9]+ { return newToken(REGISTER); } 356 357 "build" | "runtime" | "system" { 358 return newToken(ANNOTATION_VISIBILITY); 359 } 360 361 "public" | "private" | "protected" | "static" | "final" | "synchronized" | "bridge" | "varargs" | "native" | 362 "abstract" | "strictfp" | "synthetic" | "constructor" | "declared-synchronized" | "interface" | "enum" | 363 "annotation" | "volatile" | "transient" { 364 return newToken(ACCESS_SPEC); 365 } 366 367 "no-error" | "generic-error" | "no-such-class" | "no-such-field" | "no-such-method" | "illegal-class-access" | 368 "illegal-field-access" | "illegal-method-access" | "class-change-error" | "instantiation-error" { 369 return newToken(VERIFICATION_ERROR_TYPE); 370 } 371 372 "vtable@0x" {HexDigit}+ { return newToken(VTABLE_OFFSET); } 373 "field@0x" {HexDigit}+ { return newToken(FIELD_OFFSET); } 374 375 "+" {Integer} { return newToken(OFFSET); } 376 377 # [^\r\n]* { return newToken(LINE_COMMENT, true); } 378 } 379 380 /*Instructions*/ 381 <YYINITIAL> { 382 "goto" { 383 return newToken(INSTRUCTION_FORMAT10t); 384 } 385 386 "return-void" | "nop" { 387 return newToken(INSTRUCTION_FORMAT10x); 388 } 389 390 "const/4" { 391 return newToken(INSTRUCTION_FORMAT11n); 392 } 393 394 "move-result" | "move-result-wide" | "move-result-object" | "move-exception" | "return" | "return-wide" | 395 "return-object" | "monitor-enter" | "monitor-exit" | "throw" { 396 return newToken(INSTRUCTION_FORMAT11x); 397 } 398 399 "move" | "move-wide" | "move-object" | "array-length" | "neg-int" | "not-int" | "neg-long" | "not-long" | 400 "neg-float" | "neg-double" | "int-to-long" | "int-to-float" | "int-to-double" | "long-to-int" | "long-to-float" | 401 "long-to-double" | "float-to-int" | "float-to-long" | "float-to-double" | "double-to-int" | "double-to-long" | 402 "double-to-float" | "int-to-byte" | "int-to-char" | "int-to-short" { 403 return newToken(INSTRUCTION_FORMAT12x_OR_ID); 404 } 405 406 "add-int/2addr" | "sub-int/2addr" | "mul-int/2addr" | "div-int/2addr" | "rem-int/2addr" | "and-int/2addr" | 407 "or-int/2addr" | "xor-int/2addr" | "shl-int/2addr" | "shr-int/2addr" | "ushr-int/2addr" | "add-long/2addr" | 408 "sub-long/2addr" | "mul-long/2addr" | "div-long/2addr" | "rem-long/2addr" | "and-long/2addr" | "or-long/2addr" | 409 "xor-long/2addr" | "shl-long/2addr" | "shr-long/2addr" | "ushr-long/2addr" | "add-float/2addr" | 410 "sub-float/2addr" | "mul-float/2addr" | "div-float/2addr" | "rem-float/2addr" | "add-double/2addr" | 411 "sub-double/2addr" | "mul-double/2addr" | "div-double/2addr" | "rem-double/2addr" { 412 return newToken(INSTRUCTION_FORMAT12x); 413 } 414 415 "throw-verification-error" { 416 return newToken(INSTRUCTION_FORMAT20bc); 417 } 418 419 "goto/16" { 420 return newToken(INSTRUCTION_FORMAT20t); 421 } 422 423 "sget" | "sget-wide" | "sget-object" | "sget-boolean" | "sget-byte" | "sget-char" | "sget-short" | "sput" | 424 "sput-wide" | "sput-object" | "sput-boolean" | "sput-byte" | "sput-char" | "sput-short" { 425 return newToken(INSTRUCTION_FORMAT21c_FIELD); 426 } 427 428 "sget-volatile" | "sget-wide-volatile" | "sget-object-volatile" | "sput-volatile" | "sput-wide-volatile" | 429 "sput-object-volatile" { 430 return newToken(INSTRUCTION_FORMAT21c_FIELD_ODEX); 431 } 432 433 "const-string" { 434 return newToken(INSTRUCTION_FORMAT21c_STRING); 435 } 436 437 "check-cast" | "new-instance" | "const-class" { 438 return newToken(INSTRUCTION_FORMAT21c_TYPE); 439 } 440 441 "const/high16" | "const-wide/high16" { 442 return newToken(INSTRUCTION_FORMAT21h); 443 } 444 445 "const/16" | "const-wide/16" { 446 return newToken(INSTRUCTION_FORMAT21s); 447 } 448 449 "if-eqz" | "if-nez" | "if-ltz" | "if-gez" | "if-gtz" | "if-lez" { 450 return newToken(INSTRUCTION_FORMAT21t); 451 } 452 453 "add-int/lit8" | "rsub-int/lit8" | "mul-int/lit8" | "div-int/lit8" | "rem-int/lit8" | "and-int/lit8" | 454 "or-int/lit8" | "xor-int/lit8" | "shl-int/lit8" | "shr-int/lit8" | "ushr-int/lit8" { 455 return newToken(INSTRUCTION_FORMAT22b); 456 } 457 458 "iget" | "iget-wide" | "iget-object" | "iget-boolean" | "iget-byte" | "iget-char" | "iget-short" | "iput" | 459 "iput-wide" | "iput-object" | "iput-boolean" | "iput-byte" | "iput-char" | "iput-short" { 460 return newToken(INSTRUCTION_FORMAT22c_FIELD); 461 } 462 463 "iget-volatile" | "iget-wide-volatile" | "iget-object-volatile" | "iput-volatile" | "iput-wide-volatile" | 464 "iput-object-volatile" { 465 return newToken(INSTRUCTION_FORMAT22c_FIELD_ODEX); 466 } 467 468 "instance-of" | "new-array" { 469 return newToken(INSTRUCTION_FORMAT22c_TYPE); 470 } 471 472 "iget-quick" | "iget-wide-quick" | "iget-object-quick" | "iput-quick" | "iput-wide-quick" | "iput-object-quick" { 473 return newToken(INSTRUCTION_FORMAT22cs_FIELD); 474 } 475 476 "rsub-int" { 477 return newToken(INSTRUCTION_FORMAT22s_OR_ID); 478 } 479 480 "add-int/lit16" | "mul-int/lit16" | "div-int/lit16" | "rem-int/lit16" | "and-int/lit16" | "or-int/lit16" | 481 "xor-int/lit16" { 482 return newToken(INSTRUCTION_FORMAT22s); 483 } 484 485 "if-eq" | "if-ne" | "if-lt" | "if-ge" | "if-gt" | "if-le" { 486 return newToken(INSTRUCTION_FORMAT22t); 487 } 488 489 "move/from16" | "move-wide/from16" | "move-object/from16" { 490 return newToken(INSTRUCTION_FORMAT22x); 491 } 492 493 "cmpl-float" | "cmpg-float" | "cmpl-double" | "cmpg-double" | "cmp-long" | "aget" | "aget-wide" | "aget-object" | 494 "aget-boolean" | "aget-byte" | "aget-char" | "aget-short" | "aput" | "aput-wide" | "aput-object" | "aput-boolean" | 495 "aput-byte" | "aput-char" | "aput-short" | "add-int" | "sub-int" | "mul-int" | "div-int" | "rem-int" | "and-int" | 496 "or-int" | "xor-int" | "shl-int" | "shr-int" | "ushr-int" | "add-long" | "sub-long" | "mul-long" | "div-long" | 497 "rem-long" | "and-long" | "or-long" | "xor-long" | "shl-long" | "shr-long" | "ushr-long" | "add-float" | 498 "sub-float" | "mul-float" | "div-float" | "rem-float" | "add-double" | "sub-double" | "mul-double" | "div-double" | 499 "rem-double" { 500 return newToken(INSTRUCTION_FORMAT23x); 501 } 502 503 "goto/32" { 504 return newToken(INSTRUCTION_FORMAT30t); 505 } 506 507 "const-string/jumbo" { 508 return newToken(INSTRUCTION_FORMAT31c); 509 } 510 511 "const" { 512 return newToken(INSTRUCTION_FORMAT31i_OR_ID); 513 } 514 515 "const-wide/32" { 516 return newToken(INSTRUCTION_FORMAT31i); 517 } 518 519 "fill-array-data" | "packed-switch" | "sparse-switch" { 520 return newToken(INSTRUCTION_FORMAT31t); 521 } 522 523 "move/16" | "move-wide/16" | "move-object/16" { 524 return newToken(INSTRUCTION_FORMAT32x); 525 } 526 527 "invoke-virtual" | "invoke-super" | "invoke-direct" | "invoke-static" | "invoke-interface" { 528 return newToken(INSTRUCTION_FORMAT35c_METHOD); 529 } 530 531 "filled-new-array" { 532 return newToken(INSTRUCTION_FORMAT35c_TYPE); 533 } 534 535 "invoke-direct-empty" { 536 return newToken(INSTRUCTION_FORMAT35s_METHOD); 537 } 538 539 "execute-inline" | "invoke-virtual-quick" | "invoke-super-quick" { 540 return newToken(INSTRUCTION_FORMAT35ms_METHOD); 541 } 542 543 "invoke-virtual/range" | "invoke-super/range" | "invoke-direct/range" | "invoke-static/range" | 544 "invoke-interface/range" { 545 return newToken(INSTRUCTION_FORMAT3rc_METHOD); 546 } 547 548 "filled-new-array/range" { 549 return newToken(INSTRUCTION_FORMAT3rc_TYPE); 550 } 551 552 "execute-inline/range" | "invoke-virtual-quick/range" | "invoke-super-quick/range" { 553 return newToken(INSTRUCTION_FORMAT3rms_METHOD); 554 } 555 556 "const-wide" { 557 return newToken(INSTRUCTION_FORMAT51l); 558 } 559 } 560 561 /*Types*/ 562 <YYINITIAL> { 563 {PrimitiveType} { return newToken(PRIMITIVE_TYPE); } 564 V { return newToken(VOID_TYPE); } 565 {ClassDescriptor} { return newToken(CLASS_DESCRIPTOR); } 566 {ArrayDescriptor} { return newToken(ARRAY_DESCRIPTOR); } 567 {PrimitiveType} {PrimitiveType}+ { return newToken(PARAM_LIST_OR_ID); } 568 {Type} {Type}+ { return newToken(PARAM_LIST); } 569 {SimpleName} { return newToken(SIMPLE_NAME); } 570 "<init>" | "<clinit>" { return newToken(METHOD_NAME); } 571 } 572 573 /*Symbols/Whitespace/EOF*/ 574 <YYINITIAL> { 575 ".." { return newToken(DOTDOT); } 576 "->" { return newToken(ARROW); } 577 "=" { return newToken(EQUAL); } 578 ":" { return newToken(COLON); } 579 "," { return newToken(COMMA); } 580 "{" { return newToken(OPEN_BRACE); } 581 "}" { return newToken(CLOSE_BRACE); } 582 "(" { return newToken(OPEN_PAREN); } 583 ")" { return newToken(CLOSE_PAREN); } 584 [\r\n\t ]+ { return newToken(WHITE_SPACE, true); } 585 <<EOF>> { return newToken(EOF); } 586 } 587 588 /*catch all*/ 589 <YYINITIAL> { 590 "." { return invalidToken("Invalid directive"); } 591 "." [a-zA-z\-_] { return invalidToken("Invalid directive"); } 592 "." [a-zA-z\-_] [a-zA-z0-9\-_]* { return invalidToken("Invalid directive"); } 593 . { return invalidToken("Invalid text"); } 594 } 595