Ninja
|
00001 /* Generated by re2c 0.13.5 */ 00002 // Copyright 2011 Google Inc. All Rights Reserved. 00003 // 00004 // Licensed under the Apache License, Version 2.0 (the "License"); 00005 // you may not use this file except in compliance with the License. 00006 // You may obtain a copy of the License at 00007 // 00008 // http://www.apache.org/licenses/LICENSE-2.0 00009 // 00010 // Unless required by applicable law or agreed to in writing, software 00011 // distributed under the License is distributed on an "AS IS" BASIS, 00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 // See the License for the specific language governing permissions and 00014 // limitations under the License. 00015 00016 #include "lexer.h" 00017 00018 #include <stdio.h> 00019 00020 #include "eval_env.h" 00021 #include "util.h" 00022 00023 bool Lexer::Error(const string& message, string* err) { 00024 // Compute line/column. 00025 int line = 1; 00026 const char* context = input_.str_; 00027 for (const char* p = input_.str_; p < last_token_; ++p) { 00028 if (*p == '\n') { 00029 ++line; 00030 context = p + 1; 00031 } 00032 } 00033 int col = last_token_ ? (int)(last_token_ - context) : 0; 00034 00035 char buf[1024]; 00036 snprintf(buf, sizeof(buf), "%s:%d: ", filename_.AsString().c_str(), line); 00037 *err = buf; 00038 *err += message + "\n"; 00039 00040 // Add some context to the message. 00041 const int kTruncateColumn = 72; 00042 if (col > 0 && col < kTruncateColumn) { 00043 int len; 00044 bool truncated = true; 00045 for (len = 0; len < kTruncateColumn; ++len) { 00046 if (context[len] == 0 || context[len] == '\n') { 00047 truncated = false; 00048 break; 00049 } 00050 } 00051 *err += string(context, len); 00052 if (truncated) 00053 *err += "..."; 00054 *err += "\n"; 00055 *err += string(col, ' '); 00056 *err += "^ near here"; 00057 } 00058 00059 return false; 00060 } 00061 00062 Lexer::Lexer(const char* input) { 00063 Start("input", input); 00064 } 00065 00066 void Lexer::Start(StringPiece filename, StringPiece input) { 00067 filename_ = filename; 00068 input_ = input; 00069 ofs_ = input_.str_; 00070 last_token_ = NULL; 00071 } 00072 00073 const char* Lexer::TokenName(Token t) { 00074 switch (t) { 00075 case ERROR: return "lexing error"; 00076 case BUILD: return "'build'"; 00077 case COLON: return "':'"; 00078 case DEFAULT: return "'default'"; 00079 case EQUALS: return "'='"; 00080 case IDENT: return "identifier"; 00081 case INCLUDE: return "'include'"; 00082 case INDENT: return "indent"; 00083 case NEWLINE: return "newline"; 00084 case PIPE2: return "'||'"; 00085 case PIPE: return "'|'"; 00086 case POOL: return "'pool'"; 00087 case RULE: return "'rule'"; 00088 case SUBNINJA: return "'subninja'"; 00089 case TEOF: return "eof"; 00090 } 00091 return NULL; // not reached 00092 } 00093 00094 const char* Lexer::TokenErrorHint(Token expected) { 00095 switch (expected) { 00096 case COLON: 00097 return " ($ also escapes ':')"; 00098 default: 00099 return ""; 00100 } 00101 } 00102 00103 string Lexer::DescribeLastError() { 00104 if (last_token_) { 00105 switch (last_token_[0]) { 00106 case '\r': 00107 return "carriage returns are not allowed, use newlines"; 00108 case '\t': 00109 return "tabs are not allowed, use spaces"; 00110 } 00111 } 00112 return "lexing error"; 00113 } 00114 00115 void Lexer::UnreadToken() { 00116 ofs_ = last_token_; 00117 } 00118 00119 Lexer::Token Lexer::ReadToken() { 00120 const char* p = ofs_; 00121 const char* q; 00122 const char* start; 00123 Lexer::Token token; 00124 for (;;) { 00125 start = p; 00126 00127 { 00128 unsigned char yych; 00129 unsigned int yyaccept = 0; 00130 static const unsigned char yybm[] = { 00131 0, 64, 64, 64, 64, 64, 64, 64, 00132 64, 64, 0, 64, 64, 0, 64, 64, 00133 64, 64, 64, 64, 64, 64, 64, 64, 00134 64, 64, 64, 64, 64, 64, 64, 64, 00135 192, 64, 64, 64, 64, 64, 64, 64, 00136 64, 64, 64, 64, 64, 96, 96, 64, 00137 96, 96, 96, 96, 96, 96, 96, 96, 00138 96, 96, 64, 64, 64, 64, 64, 64, 00139 64, 96, 96, 96, 96, 96, 96, 96, 00140 96, 96, 96, 96, 96, 96, 96, 96, 00141 96, 96, 96, 96, 96, 96, 96, 96, 00142 96, 96, 96, 64, 64, 64, 64, 96, 00143 64, 96, 96, 96, 96, 96, 96, 96, 00144 96, 96, 96, 96, 96, 96, 96, 96, 00145 96, 96, 96, 96, 96, 96, 96, 96, 00146 96, 96, 96, 64, 64, 64, 64, 64, 00147 64, 64, 64, 64, 64, 64, 64, 64, 00148 64, 64, 64, 64, 64, 64, 64, 64, 00149 64, 64, 64, 64, 64, 64, 64, 64, 00150 64, 64, 64, 64, 64, 64, 64, 64, 00151 64, 64, 64, 64, 64, 64, 64, 64, 00152 64, 64, 64, 64, 64, 64, 64, 64, 00153 64, 64, 64, 64, 64, 64, 64, 64, 00154 64, 64, 64, 64, 64, 64, 64, 64, 00155 64, 64, 64, 64, 64, 64, 64, 64, 00156 64, 64, 64, 64, 64, 64, 64, 64, 00157 64, 64, 64, 64, 64, 64, 64, 64, 00158 64, 64, 64, 64, 64, 64, 64, 64, 00159 64, 64, 64, 64, 64, 64, 64, 64, 00160 64, 64, 64, 64, 64, 64, 64, 64, 00161 64, 64, 64, 64, 64, 64, 64, 64, 00162 64, 64, 64, 64, 64, 64, 64, 64, 00163 }; 00164 00165 yych = *p; 00166 if (yych <= '^') { 00167 if (yych <= ',') { 00168 if (yych <= 0x1F) { 00169 if (yych <= 0x00) goto yy22; 00170 if (yych == '\n') goto yy6; 00171 goto yy24; 00172 } else { 00173 if (yych <= ' ') goto yy2; 00174 if (yych == '#') goto yy4; 00175 goto yy24; 00176 } 00177 } else { 00178 if (yych <= ':') { 00179 if (yych == '/') goto yy24; 00180 if (yych <= '9') goto yy21; 00181 goto yy15; 00182 } else { 00183 if (yych <= '=') { 00184 if (yych <= '<') goto yy24; 00185 goto yy13; 00186 } else { 00187 if (yych <= '@') goto yy24; 00188 if (yych <= 'Z') goto yy21; 00189 goto yy24; 00190 } 00191 } 00192 } 00193 } else { 00194 if (yych <= 'i') { 00195 if (yych <= 'b') { 00196 if (yych == '`') goto yy24; 00197 if (yych <= 'a') goto yy21; 00198 goto yy8; 00199 } else { 00200 if (yych == 'd') goto yy12; 00201 if (yych <= 'h') goto yy21; 00202 goto yy19; 00203 } 00204 } else { 00205 if (yych <= 'r') { 00206 if (yych == 'p') goto yy10; 00207 if (yych <= 'q') goto yy21; 00208 goto yy11; 00209 } else { 00210 if (yych <= 'z') { 00211 if (yych <= 's') goto yy20; 00212 goto yy21; 00213 } else { 00214 if (yych == '|') goto yy17; 00215 goto yy24; 00216 } 00217 } 00218 } 00219 } 00220 yy2: 00221 yyaccept = 0; 00222 yych = *(q = ++p); 00223 goto yy70; 00224 yy3: 00225 { token = INDENT; break; } 00226 yy4: 00227 yyaccept = 1; 00228 yych = *(q = ++p); 00229 if (yych <= 0x00) goto yy5; 00230 if (yych != '\r') goto yy65; 00231 yy5: 00232 { token = ERROR; break; } 00233 yy6: 00234 ++p; 00235 yy7: 00236 { token = NEWLINE; break; } 00237 yy8: 00238 ++p; 00239 if ((yych = *p) == 'u') goto yy59; 00240 goto yy26; 00241 yy9: 00242 { token = IDENT; break; } 00243 yy10: 00244 yych = *++p; 00245 if (yych == 'o') goto yy55; 00246 goto yy26; 00247 yy11: 00248 yych = *++p; 00249 if (yych == 'u') goto yy51; 00250 goto yy26; 00251 yy12: 00252 yych = *++p; 00253 if (yych == 'e') goto yy44; 00254 goto yy26; 00255 yy13: 00256 ++p; 00257 { token = EQUALS; break; } 00258 yy15: 00259 ++p; 00260 { token = COLON; break; } 00261 yy17: 00262 ++p; 00263 if ((yych = *p) == '|') goto yy42; 00264 { token = PIPE; break; } 00265 yy19: 00266 yych = *++p; 00267 if (yych == 'n') goto yy35; 00268 goto yy26; 00269 yy20: 00270 yych = *++p; 00271 if (yych == 'u') goto yy27; 00272 goto yy26; 00273 yy21: 00274 yych = *++p; 00275 goto yy26; 00276 yy22: 00277 ++p; 00278 { token = TEOF; break; } 00279 yy24: 00280 yych = *++p; 00281 goto yy5; 00282 yy25: 00283 ++p; 00284 yych = *p; 00285 yy26: 00286 if (yybm[0+yych] & 32) { 00287 goto yy25; 00288 } 00289 goto yy9; 00290 yy27: 00291 yych = *++p; 00292 if (yych != 'b') goto yy26; 00293 yych = *++p; 00294 if (yych != 'n') goto yy26; 00295 yych = *++p; 00296 if (yych != 'i') goto yy26; 00297 yych = *++p; 00298 if (yych != 'n') goto yy26; 00299 yych = *++p; 00300 if (yych != 'j') goto yy26; 00301 yych = *++p; 00302 if (yych != 'a') goto yy26; 00303 ++p; 00304 if (yybm[0+(yych = *p)] & 32) { 00305 goto yy25; 00306 } 00307 { token = SUBNINJA; break; } 00308 yy35: 00309 yych = *++p; 00310 if (yych != 'c') goto yy26; 00311 yych = *++p; 00312 if (yych != 'l') goto yy26; 00313 yych = *++p; 00314 if (yych != 'u') goto yy26; 00315 yych = *++p; 00316 if (yych != 'd') goto yy26; 00317 yych = *++p; 00318 if (yych != 'e') goto yy26; 00319 ++p; 00320 if (yybm[0+(yych = *p)] & 32) { 00321 goto yy25; 00322 } 00323 { token = INCLUDE; break; } 00324 yy42: 00325 ++p; 00326 { token = PIPE2; break; } 00327 yy44: 00328 yych = *++p; 00329 if (yych != 'f') goto yy26; 00330 yych = *++p; 00331 if (yych != 'a') goto yy26; 00332 yych = *++p; 00333 if (yych != 'u') goto yy26; 00334 yych = *++p; 00335 if (yych != 'l') goto yy26; 00336 yych = *++p; 00337 if (yych != 't') goto yy26; 00338 ++p; 00339 if (yybm[0+(yych = *p)] & 32) { 00340 goto yy25; 00341 } 00342 { token = DEFAULT; break; } 00343 yy51: 00344 yych = *++p; 00345 if (yych != 'l') goto yy26; 00346 yych = *++p; 00347 if (yych != 'e') goto yy26; 00348 ++p; 00349 if (yybm[0+(yych = *p)] & 32) { 00350 goto yy25; 00351 } 00352 { token = RULE; break; } 00353 yy55: 00354 yych = *++p; 00355 if (yych != 'o') goto yy26; 00356 yych = *++p; 00357 if (yych != 'l') goto yy26; 00358 ++p; 00359 if (yybm[0+(yych = *p)] & 32) { 00360 goto yy25; 00361 } 00362 { token = POOL; break; } 00363 yy59: 00364 yych = *++p; 00365 if (yych != 'i') goto yy26; 00366 yych = *++p; 00367 if (yych != 'l') goto yy26; 00368 yych = *++p; 00369 if (yych != 'd') goto yy26; 00370 ++p; 00371 if (yybm[0+(yych = *p)] & 32) { 00372 goto yy25; 00373 } 00374 { token = BUILD; break; } 00375 yy64: 00376 ++p; 00377 yych = *p; 00378 yy65: 00379 if (yybm[0+yych] & 64) { 00380 goto yy64; 00381 } 00382 if (yych <= 0x00) goto yy66; 00383 if (yych <= '\f') goto yy67; 00384 yy66: 00385 p = q; 00386 if (yyaccept <= 0) { 00387 goto yy3; 00388 } else { 00389 goto yy5; 00390 } 00391 yy67: 00392 ++p; 00393 { continue; } 00394 yy69: 00395 yyaccept = 0; 00396 q = ++p; 00397 yych = *p; 00398 yy70: 00399 if (yybm[0+yych] & 128) { 00400 goto yy69; 00401 } 00402 if (yych == '\n') goto yy71; 00403 if (yych == '#') goto yy64; 00404 goto yy3; 00405 yy71: 00406 ++p; 00407 yych = *p; 00408 goto yy7; 00409 } 00410 00411 } 00412 00413 last_token_ = start; 00414 ofs_ = p; 00415 if (token != NEWLINE && token != TEOF) 00416 EatWhitespace(); 00417 return token; 00418 } 00419 00420 bool Lexer::PeekToken(Token token) { 00421 Token t = ReadToken(); 00422 if (t == token) 00423 return true; 00424 UnreadToken(); 00425 return false; 00426 } 00427 00428 void Lexer::EatWhitespace() { 00429 const char* p = ofs_; 00430 for (;;) { 00431 ofs_ = p; 00432 00433 { 00434 unsigned char yych; 00435 static const unsigned char yybm[] = { 00436 0, 0, 0, 0, 0, 0, 0, 0, 00437 0, 0, 0, 0, 0, 0, 0, 0, 00438 0, 0, 0, 0, 0, 0, 0, 0, 00439 0, 0, 0, 0, 0, 0, 0, 0, 00440 128, 0, 0, 0, 0, 0, 0, 0, 00441 0, 0, 0, 0, 0, 0, 0, 0, 00442 0, 0, 0, 0, 0, 0, 0, 0, 00443 0, 0, 0, 0, 0, 0, 0, 0, 00444 0, 0, 0, 0, 0, 0, 0, 0, 00445 0, 0, 0, 0, 0, 0, 0, 0, 00446 0, 0, 0, 0, 0, 0, 0, 0, 00447 0, 0, 0, 0, 0, 0, 0, 0, 00448 0, 0, 0, 0, 0, 0, 0, 0, 00449 0, 0, 0, 0, 0, 0, 0, 0, 00450 0, 0, 0, 0, 0, 0, 0, 0, 00451 0, 0, 0, 0, 0, 0, 0, 0, 00452 0, 0, 0, 0, 0, 0, 0, 0, 00453 0, 0, 0, 0, 0, 0, 0, 0, 00454 0, 0, 0, 0, 0, 0, 0, 0, 00455 0, 0, 0, 0, 0, 0, 0, 0, 00456 0, 0, 0, 0, 0, 0, 0, 0, 00457 0, 0, 0, 0, 0, 0, 0, 0, 00458 0, 0, 0, 0, 0, 0, 0, 0, 00459 0, 0, 0, 0, 0, 0, 0, 0, 00460 0, 0, 0, 0, 0, 0, 0, 0, 00461 0, 0, 0, 0, 0, 0, 0, 0, 00462 0, 0, 0, 0, 0, 0, 0, 0, 00463 0, 0, 0, 0, 0, 0, 0, 0, 00464 0, 0, 0, 0, 0, 0, 0, 0, 00465 0, 0, 0, 0, 0, 0, 0, 0, 00466 0, 0, 0, 0, 0, 0, 0, 0, 00467 0, 0, 0, 0, 0, 0, 0, 0, 00468 }; 00469 yych = *p; 00470 if (yych <= ' ') { 00471 if (yych <= 0x00) goto yy78; 00472 if (yych <= 0x1F) goto yy80; 00473 } else { 00474 if (yych == '$') goto yy76; 00475 goto yy80; 00476 } 00477 ++p; 00478 yych = *p; 00479 goto yy84; 00480 yy75: 00481 { continue; } 00482 yy76: 00483 ++p; 00484 if ((yych = *p) == '\n') goto yy81; 00485 yy77: 00486 { break; } 00487 yy78: 00488 ++p; 00489 { break; } 00490 yy80: 00491 yych = *++p; 00492 goto yy77; 00493 yy81: 00494 ++p; 00495 { continue; } 00496 yy83: 00497 ++p; 00498 yych = *p; 00499 yy84: 00500 if (yybm[0+yych] & 128) { 00501 goto yy83; 00502 } 00503 goto yy75; 00504 } 00505 00506 } 00507 } 00508 00509 bool Lexer::ReadIdent(string* out) { 00510 const char* p = ofs_; 00511 for (;;) { 00512 const char* start = p; 00513 00514 { 00515 unsigned char yych; 00516 static const unsigned char yybm[] = { 00517 0, 0, 0, 0, 0, 0, 0, 0, 00518 0, 0, 0, 0, 0, 0, 0, 0, 00519 0, 0, 0, 0, 0, 0, 0, 0, 00520 0, 0, 0, 0, 0, 0, 0, 0, 00521 0, 0, 0, 0, 0, 0, 0, 0, 00522 0, 0, 0, 0, 0, 128, 128, 0, 00523 128, 128, 128, 128, 128, 128, 128, 128, 00524 128, 128, 0, 0, 0, 0, 0, 0, 00525 0, 128, 128, 128, 128, 128, 128, 128, 00526 128, 128, 128, 128, 128, 128, 128, 128, 00527 128, 128, 128, 128, 128, 128, 128, 128, 00528 128, 128, 128, 0, 0, 0, 0, 128, 00529 0, 128, 128, 128, 128, 128, 128, 128, 00530 128, 128, 128, 128, 128, 128, 128, 128, 00531 128, 128, 128, 128, 128, 128, 128, 128, 00532 128, 128, 128, 0, 0, 0, 0, 0, 00533 0, 0, 0, 0, 0, 0, 0, 0, 00534 0, 0, 0, 0, 0, 0, 0, 0, 00535 0, 0, 0, 0, 0, 0, 0, 0, 00536 0, 0, 0, 0, 0, 0, 0, 0, 00537 0, 0, 0, 0, 0, 0, 0, 0, 00538 0, 0, 0, 0, 0, 0, 0, 0, 00539 0, 0, 0, 0, 0, 0, 0, 0, 00540 0, 0, 0, 0, 0, 0, 0, 0, 00541 0, 0, 0, 0, 0, 0, 0, 0, 00542 0, 0, 0, 0, 0, 0, 0, 0, 00543 0, 0, 0, 0, 0, 0, 0, 0, 00544 0, 0, 0, 0, 0, 0, 0, 0, 00545 0, 0, 0, 0, 0, 0, 0, 0, 00546 0, 0, 0, 0, 0, 0, 0, 0, 00547 0, 0, 0, 0, 0, 0, 0, 0, 00548 0, 0, 0, 0, 0, 0, 0, 0, 00549 }; 00550 yych = *p; 00551 if (yych <= '@') { 00552 if (yych <= '.') { 00553 if (yych <= ',') goto yy89; 00554 } else { 00555 if (yych <= '/') goto yy89; 00556 if (yych >= ':') goto yy89; 00557 } 00558 } else { 00559 if (yych <= '_') { 00560 if (yych <= 'Z') goto yy87; 00561 if (yych <= '^') goto yy89; 00562 } else { 00563 if (yych <= '`') goto yy89; 00564 if (yych >= '{') goto yy89; 00565 } 00566 } 00567 yy87: 00568 ++p; 00569 yych = *p; 00570 goto yy92; 00571 yy88: 00572 { 00573 out->assign(start, p - start); 00574 break; 00575 } 00576 yy89: 00577 ++p; 00578 { return false; } 00579 yy91: 00580 ++p; 00581 yych = *p; 00582 yy92: 00583 if (yybm[0+yych] & 128) { 00584 goto yy91; 00585 } 00586 goto yy88; 00587 } 00588 00589 } 00590 ofs_ = p; 00591 EatWhitespace(); 00592 return true; 00593 } 00594 00595 bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) { 00596 const char* p = ofs_; 00597 const char* q; 00598 const char* start; 00599 for (;;) { 00600 start = p; 00601 00602 { 00603 unsigned char yych; 00604 static const unsigned char yybm[] = { 00605 0, 128, 128, 128, 128, 128, 128, 128, 00606 128, 128, 0, 128, 128, 0, 128, 128, 00607 128, 128, 128, 128, 128, 128, 128, 128, 00608 128, 128, 128, 128, 128, 128, 128, 128, 00609 16, 128, 128, 128, 0, 128, 128, 128, 00610 128, 128, 128, 128, 128, 224, 160, 128, 00611 224, 224, 224, 224, 224, 224, 224, 224, 00612 224, 224, 0, 128, 128, 128, 128, 128, 00613 128, 224, 224, 224, 224, 224, 224, 224, 00614 224, 224, 224, 224, 224, 224, 224, 224, 00615 224, 224, 224, 224, 224, 224, 224, 224, 00616 224, 224, 224, 128, 128, 128, 128, 224, 00617 128, 224, 224, 224, 224, 224, 224, 224, 00618 224, 224, 224, 224, 224, 224, 224, 224, 00619 224, 224, 224, 224, 224, 224, 224, 224, 00620 224, 224, 224, 128, 0, 128, 128, 128, 00621 128, 128, 128, 128, 128, 128, 128, 128, 00622 128, 128, 128, 128, 128, 128, 128, 128, 00623 128, 128, 128, 128, 128, 128, 128, 128, 00624 128, 128, 128, 128, 128, 128, 128, 128, 00625 128, 128, 128, 128, 128, 128, 128, 128, 00626 128, 128, 128, 128, 128, 128, 128, 128, 00627 128, 128, 128, 128, 128, 128, 128, 128, 00628 128, 128, 128, 128, 128, 128, 128, 128, 00629 128, 128, 128, 128, 128, 128, 128, 128, 00630 128, 128, 128, 128, 128, 128, 128, 128, 00631 128, 128, 128, 128, 128, 128, 128, 128, 00632 128, 128, 128, 128, 128, 128, 128, 128, 00633 128, 128, 128, 128, 128, 128, 128, 128, 00634 128, 128, 128, 128, 128, 128, 128, 128, 00635 128, 128, 128, 128, 128, 128, 128, 128, 00636 128, 128, 128, 128, 128, 128, 128, 128, 00637 }; 00638 yych = *p; 00639 if (yych <= ' ') { 00640 if (yych <= '\n') { 00641 if (yych <= 0x00) goto yy101; 00642 if (yych >= '\n') goto yy97; 00643 } else { 00644 if (yych == '\r') goto yy103; 00645 if (yych >= ' ') goto yy97; 00646 } 00647 } else { 00648 if (yych <= '9') { 00649 if (yych == '$') goto yy99; 00650 } else { 00651 if (yych <= ':') goto yy97; 00652 if (yych == '|') goto yy97; 00653 } 00654 } 00655 ++p; 00656 yych = *p; 00657 goto yy126; 00658 yy96: 00659 { 00660 eval->AddText(StringPiece(start, p - start)); 00661 continue; 00662 } 00663 yy97: 00664 ++p; 00665 { 00666 if (path) { 00667 p = start; 00668 break; 00669 } else { 00670 if (*start == '\n') 00671 break; 00672 eval->AddText(StringPiece(start, 1)); 00673 continue; 00674 } 00675 } 00676 yy99: 00677 ++p; 00678 if ((yych = *p) <= '/') { 00679 if (yych <= ' ') { 00680 if (yych == '\n') goto yy115; 00681 if (yych <= 0x1F) goto yy104; 00682 goto yy106; 00683 } else { 00684 if (yych <= '$') { 00685 if (yych <= '#') goto yy104; 00686 goto yy108; 00687 } else { 00688 if (yych == '-') goto yy110; 00689 goto yy104; 00690 } 00691 } 00692 } else { 00693 if (yych <= '^') { 00694 if (yych <= ':') { 00695 if (yych <= '9') goto yy110; 00696 goto yy112; 00697 } else { 00698 if (yych <= '@') goto yy104; 00699 if (yych <= 'Z') goto yy110; 00700 goto yy104; 00701 } 00702 } else { 00703 if (yych <= '`') { 00704 if (yych <= '_') goto yy110; 00705 goto yy104; 00706 } else { 00707 if (yych <= 'z') goto yy110; 00708 if (yych <= '{') goto yy114; 00709 goto yy104; 00710 } 00711 } 00712 } 00713 yy100: 00714 { 00715 last_token_ = start; 00716 return Error(DescribeLastError(), err); 00717 } 00718 yy101: 00719 ++p; 00720 { 00721 last_token_ = start; 00722 return Error("unexpected EOF", err); 00723 } 00724 yy103: 00725 yych = *++p; 00726 goto yy100; 00727 yy104: 00728 ++p; 00729 yy105: 00730 { 00731 last_token_ = start; 00732 return Error("bad $-escape (literal $ must be written as $$)", err); 00733 } 00734 yy106: 00735 ++p; 00736 { 00737 eval->AddText(StringPiece(" ", 1)); 00738 continue; 00739 } 00740 yy108: 00741 ++p; 00742 { 00743 eval->AddText(StringPiece("$", 1)); 00744 continue; 00745 } 00746 yy110: 00747 ++p; 00748 yych = *p; 00749 goto yy124; 00750 yy111: 00751 { 00752 eval->AddSpecial(StringPiece(start + 1, p - start - 1)); 00753 continue; 00754 } 00755 yy112: 00756 ++p; 00757 { 00758 eval->AddText(StringPiece(":", 1)); 00759 continue; 00760 } 00761 yy114: 00762 yych = *(q = ++p); 00763 if (yybm[0+yych] & 32) { 00764 goto yy118; 00765 } 00766 goto yy105; 00767 yy115: 00768 ++p; 00769 yych = *p; 00770 if (yybm[0+yych] & 16) { 00771 goto yy115; 00772 } 00773 { 00774 continue; 00775 } 00776 yy118: 00777 ++p; 00778 yych = *p; 00779 if (yybm[0+yych] & 32) { 00780 goto yy118; 00781 } 00782 if (yych == '}') goto yy121; 00783 p = q; 00784 goto yy105; 00785 yy121: 00786 ++p; 00787 { 00788 eval->AddSpecial(StringPiece(start + 2, p - start - 3)); 00789 continue; 00790 } 00791 yy123: 00792 ++p; 00793 yych = *p; 00794 yy124: 00795 if (yybm[0+yych] & 64) { 00796 goto yy123; 00797 } 00798 goto yy111; 00799 yy125: 00800 ++p; 00801 yych = *p; 00802 yy126: 00803 if (yybm[0+yych] & 128) { 00804 goto yy125; 00805 } 00806 goto yy96; 00807 } 00808 00809 } 00810 last_token_ = start; 00811 ofs_ = p; 00812 if (path) 00813 EatWhitespace(); 00814 // Non-path strings end in newlines, so there's no whitespace to eat. 00815 return true; 00816 }