1 /* Generated by re2c 0.13.5 */
2 // Copyright 2011 Google Inc. All Rights Reserved.
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
23 bool Lexer::Error(const string& message, string* err) {
24 // Compute line/column.
26 const char* context = input_.str_;
27 for (const char* p = input_.str_; p < last_token_; ++p) {
33 int col = last_token_ ? last_token_ - context : 0;
36 snprintf(buf, sizeof(buf), "%s:%d: ", filename_.AsString().c_str(), line);
38 *err += message + "\n";
40 // Add some context to the message.
41 const int kTruncateColumn = 72;
42 if (col > 0 && col < kTruncateColumn) {
44 bool truncated = true;
45 for (len = 0; len < kTruncateColumn; ++len) {
46 if (context[len] == 0 || context[len] == '\n') {
51 *err += string(context, len);
55 *err += string(col, ' ');
56 *err += "^ near here";
62 Lexer::Lexer(const char* input) {
63 Start("input", input);
66 void Lexer::Start(StringPiece filename, StringPiece input) {
73 const char* Lexer::TokenName(Token t) {
75 case ERROR: return "lexing error";
76 case BUILD: return "'build'";
77 case COLON: return "':'";
78 case DEFAULT: return "'default'";
79 case EQUALS: return "'='";
80 case IDENT: return "identifier";
81 case INCLUDE: return "'include'";
82 case INDENT: return "indent";
83 case NEWLINE: return "newline";
84 case PIPE2: return "'||'";
85 case PIPE: return "'|'";
86 case RULE: return "'rule'";
87 case SUBNINJA: return "'subninja'";
88 case TEOF: return "eof";
90 return NULL; // not reached
93 const char* Lexer::TokenErrorHint(Token t) {
95 case ERROR: return "";
96 case BUILD: return "";
97 case COLON: return " ($ also escapes ':')";
98 case DEFAULT: return "";
99 case EQUALS: return "";
100 case IDENT: return "";
101 case INCLUDE: return "";
102 case INDENT: return "";
103 case NEWLINE: return "";
104 case PIPE2: return "";
105 case PIPE: return "";
106 case RULE: return "";
107 case SUBNINJA: return "";
108 case TEOF: return "";
113 void Lexer::UnreadToken() {
117 Lexer::Token Lexer::ReadToken() {
118 const char* p = ofs_;
127 unsigned int yyaccept = 0;
128 static const unsigned char yybm[] = {
129 0, 64, 64, 64, 64, 64, 64, 64,
130 64, 64, 0, 64, 64, 0, 64, 64,
131 64, 64, 64, 64, 64, 64, 64, 64,
132 64, 64, 64, 64, 64, 64, 64, 64,
133 192, 64, 64, 64, 64, 64, 64, 64,
134 64, 64, 64, 64, 64, 96, 96, 64,
135 96, 96, 96, 96, 96, 96, 96, 96,
136 96, 96, 64, 64, 64, 64, 64, 64,
137 64, 96, 96, 96, 96, 96, 96, 96,
138 96, 96, 96, 96, 96, 96, 96, 96,
139 96, 96, 96, 96, 96, 96, 96, 96,
140 96, 96, 96, 64, 64, 64, 64, 96,
141 64, 96, 96, 96, 96, 96, 96, 96,
142 96, 96, 96, 96, 96, 96, 96, 96,
143 96, 96, 96, 96, 96, 96, 96, 96,
144 96, 96, 96, 64, 64, 64, 64, 64,
145 64, 64, 64, 64, 64, 64, 64, 64,
146 64, 64, 64, 64, 64, 64, 64, 64,
147 64, 64, 64, 64, 64, 64, 64, 64,
148 64, 64, 64, 64, 64, 64, 64, 64,
149 64, 64, 64, 64, 64, 64, 64, 64,
150 64, 64, 64, 64, 64, 64, 64, 64,
151 64, 64, 64, 64, 64, 64, 64, 64,
152 64, 64, 64, 64, 64, 64, 64, 64,
153 64, 64, 64, 64, 64, 64, 64, 64,
154 64, 64, 64, 64, 64, 64, 64, 64,
155 64, 64, 64, 64, 64, 64, 64, 64,
156 64, 64, 64, 64, 64, 64, 64, 64,
157 64, 64, 64, 64, 64, 64, 64, 64,
158 64, 64, 64, 64, 64, 64, 64, 64,
159 64, 64, 64, 64, 64, 64, 64, 64,
160 64, 64, 64, 64, 64, 64, 64, 64,
167 if (yych <= 0x00) goto yy21;
168 if (yych == '\n') goto yy6;
171 if (yych <= ' ') goto yy2;
172 if (yych == '#') goto yy4;
177 if (yych == '/') goto yy23;
178 if (yych <= '9') goto yy20;
181 if (yych == '=') goto yy12;
182 if (yych <= '@') goto yy23;
189 if (yych == '_') goto yy20;
190 if (yych <= '`') goto yy23;
193 if (yych <= 'b') goto yy8;
194 if (yych == 'd') goto yy11;
199 if (yych <= 'i') goto yy18;
200 if (yych <= 'q') goto yy20;
201 if (yych <= 'r') goto yy10;
204 if (yych <= 'z') goto yy20;
205 if (yych == '|') goto yy16;
215 { token = INDENT; break; }
219 if (yych <= 0x00) goto yy5;
220 if (yych != '\r') goto yy60;
222 { token = ERROR; break; }
226 { token = NEWLINE; break; }
229 if ((yych = *p) == 'u') goto yy54;
232 { token = IDENT; break; }
235 if (yych == 'u') goto yy50;
239 if (yych == 'e') goto yy43;
243 { token = EQUALS; break; }
246 { token = COLON; break; }
249 if ((yych = *p) == '|') goto yy41;
250 { token = PIPE; break; }
253 if (yych == 'n') goto yy34;
257 if (yych == 'u') goto yy26;
264 { token = TEOF; break; }
272 if (yybm[0+yych] & 32) {
278 if (yych != 'b') goto yy25;
280 if (yych != 'n') goto yy25;
282 if (yych != 'i') goto yy25;
284 if (yych != 'n') goto yy25;
286 if (yych != 'j') goto yy25;
288 if (yych != 'a') goto yy25;
290 if (yybm[0+(yych = *p)] & 32) {
293 { token = SUBNINJA; break; }
296 if (yych != 'c') goto yy25;
298 if (yych != 'l') goto yy25;
300 if (yych != 'u') goto yy25;
302 if (yych != 'd') goto yy25;
304 if (yych != 'e') goto yy25;
306 if (yybm[0+(yych = *p)] & 32) {
309 { token = INCLUDE; break; }
312 { token = PIPE2; break; }
315 if (yych != 'f') goto yy25;
317 if (yych != 'a') goto yy25;
319 if (yych != 'u') goto yy25;
321 if (yych != 'l') goto yy25;
323 if (yych != 't') goto yy25;
325 if (yybm[0+(yych = *p)] & 32) {
328 { token = DEFAULT; break; }
331 if (yych != 'l') goto yy25;
333 if (yych != 'e') goto yy25;
335 if (yybm[0+(yych = *p)] & 32) {
338 { token = RULE; break; }
341 if (yych != 'i') goto yy25;
343 if (yych != 'l') goto yy25;
345 if (yych != 'd') goto yy25;
347 if (yybm[0+(yych = *p)] & 32) {
350 { token = BUILD; break; }
355 if (yybm[0+yych] & 64) {
358 if (yych <= 0x00) goto yy61;
359 if (yych <= '\f') goto yy62;
375 if (yybm[0+yych] & 128) {
378 if (yych == '\n') goto yy66;
379 if (yych == '#') goto yy59;
391 if (token != NEWLINE && token != TEOF)
396 bool Lexer::PeekToken(Token token) {
397 Token t = ReadToken();
404 void Lexer::EatWhitespace() {
405 const char* p = ofs_;
411 static const unsigned char yybm[] = {
412 0, 0, 0, 0, 0, 0, 0, 0,
413 0, 0, 0, 0, 0, 0, 0, 0,
414 0, 0, 0, 0, 0, 0, 0, 0,
415 0, 0, 0, 0, 0, 0, 0, 0,
416 128, 0, 0, 0, 0, 0, 0, 0,
417 0, 0, 0, 0, 0, 0, 0, 0,
418 0, 0, 0, 0, 0, 0, 0, 0,
419 0, 0, 0, 0, 0, 0, 0, 0,
420 0, 0, 0, 0, 0, 0, 0, 0,
421 0, 0, 0, 0, 0, 0, 0, 0,
422 0, 0, 0, 0, 0, 0, 0, 0,
423 0, 0, 0, 0, 0, 0, 0, 0,
424 0, 0, 0, 0, 0, 0, 0, 0,
425 0, 0, 0, 0, 0, 0, 0, 0,
426 0, 0, 0, 0, 0, 0, 0, 0,
427 0, 0, 0, 0, 0, 0, 0, 0,
428 0, 0, 0, 0, 0, 0, 0, 0,
429 0, 0, 0, 0, 0, 0, 0, 0,
430 0, 0, 0, 0, 0, 0, 0, 0,
431 0, 0, 0, 0, 0, 0, 0, 0,
432 0, 0, 0, 0, 0, 0, 0, 0,
433 0, 0, 0, 0, 0, 0, 0, 0,
434 0, 0, 0, 0, 0, 0, 0, 0,
435 0, 0, 0, 0, 0, 0, 0, 0,
436 0, 0, 0, 0, 0, 0, 0, 0,
437 0, 0, 0, 0, 0, 0, 0, 0,
438 0, 0, 0, 0, 0, 0, 0, 0,
439 0, 0, 0, 0, 0, 0, 0, 0,
440 0, 0, 0, 0, 0, 0, 0, 0,
441 0, 0, 0, 0, 0, 0, 0, 0,
442 0, 0, 0, 0, 0, 0, 0, 0,
443 0, 0, 0, 0, 0, 0, 0, 0,
447 if (yych <= 0x00) goto yy73;
448 if (yych <= 0x1F) goto yy75;
450 if (yych == '$') goto yy71;
460 if ((yych = *p) == '\n') goto yy76;
476 if (yybm[0+yych] & 128) {
485 bool Lexer::ReadIdent(string* out) {
486 const char* p = ofs_;
488 const char* start = p;
492 static const unsigned char yybm[] = {
493 0, 0, 0, 0, 0, 0, 0, 0,
494 0, 0, 0, 0, 0, 0, 0, 0,
495 0, 0, 0, 0, 0, 0, 0, 0,
496 0, 0, 0, 0, 0, 0, 0, 0,
497 0, 0, 0, 0, 0, 0, 0, 0,
498 0, 0, 0, 0, 0, 128, 128, 0,
499 128, 128, 128, 128, 128, 128, 128, 128,
500 128, 128, 0, 0, 0, 0, 0, 0,
501 0, 128, 128, 128, 128, 128, 128, 128,
502 128, 128, 128, 128, 128, 128, 128, 128,
503 128, 128, 128, 128, 128, 128, 128, 128,
504 128, 128, 128, 0, 0, 0, 0, 128,
505 0, 128, 128, 128, 128, 128, 128, 128,
506 128, 128, 128, 128, 128, 128, 128, 128,
507 128, 128, 128, 128, 128, 128, 128, 128,
508 128, 128, 128, 0, 0, 0, 0, 0,
509 0, 0, 0, 0, 0, 0, 0, 0,
510 0, 0, 0, 0, 0, 0, 0, 0,
511 0, 0, 0, 0, 0, 0, 0, 0,
512 0, 0, 0, 0, 0, 0, 0, 0,
513 0, 0, 0, 0, 0, 0, 0, 0,
514 0, 0, 0, 0, 0, 0, 0, 0,
515 0, 0, 0, 0, 0, 0, 0, 0,
516 0, 0, 0, 0, 0, 0, 0, 0,
517 0, 0, 0, 0, 0, 0, 0, 0,
518 0, 0, 0, 0, 0, 0, 0, 0,
519 0, 0, 0, 0, 0, 0, 0, 0,
520 0, 0, 0, 0, 0, 0, 0, 0,
521 0, 0, 0, 0, 0, 0, 0, 0,
522 0, 0, 0, 0, 0, 0, 0, 0,
523 0, 0, 0, 0, 0, 0, 0, 0,
524 0, 0, 0, 0, 0, 0, 0, 0,
529 if (yych <= ',') goto yy84;
531 if (yych <= '/') goto yy84;
532 if (yych >= ':') goto yy84;
536 if (yych <= 'Z') goto yy82;
537 if (yych <= '^') goto yy84;
539 if (yych <= '`') goto yy84;
540 if (yych >= '{') goto yy84;
549 out->assign(start, p - start);
559 if (yybm[0+yych] & 128) {
571 bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) {
572 const char* p = ofs_;
580 static const unsigned char yybm[] = {
581 0, 128, 128, 128, 128, 128, 128, 128,
582 128, 128, 0, 128, 128, 0, 128, 128,
583 128, 128, 128, 128, 128, 128, 128, 128,
584 128, 128, 128, 128, 128, 128, 128, 128,
585 16, 128, 128, 128, 0, 128, 128, 128,
586 128, 128, 128, 128, 128, 224, 160, 128,
587 224, 224, 224, 224, 224, 224, 224, 224,
588 224, 224, 0, 128, 128, 128, 128, 128,
589 128, 224, 224, 224, 224, 224, 224, 224,
590 224, 224, 224, 224, 224, 224, 224, 224,
591 224, 224, 224, 224, 224, 224, 224, 224,
592 224, 224, 224, 128, 128, 128, 128, 224,
593 128, 224, 224, 224, 224, 224, 224, 224,
594 224, 224, 224, 224, 224, 224, 224, 224,
595 224, 224, 224, 224, 224, 224, 224, 224,
596 224, 224, 224, 128, 0, 128, 128, 128,
597 128, 128, 128, 128, 128, 128, 128, 128,
598 128, 128, 128, 128, 128, 128, 128, 128,
599 128, 128, 128, 128, 128, 128, 128, 128,
600 128, 128, 128, 128, 128, 128, 128, 128,
601 128, 128, 128, 128, 128, 128, 128, 128,
602 128, 128, 128, 128, 128, 128, 128, 128,
603 128, 128, 128, 128, 128, 128, 128, 128,
604 128, 128, 128, 128, 128, 128, 128, 128,
605 128, 128, 128, 128, 128, 128, 128, 128,
606 128, 128, 128, 128, 128, 128, 128, 128,
607 128, 128, 128, 128, 128, 128, 128, 128,
608 128, 128, 128, 128, 128, 128, 128, 128,
609 128, 128, 128, 128, 128, 128, 128, 128,
610 128, 128, 128, 128, 128, 128, 128, 128,
611 128, 128, 128, 128, 128, 128, 128, 128,
612 128, 128, 128, 128, 128, 128, 128, 128,
617 if (yych <= 0x00) goto yy96;
618 if (yych >= '\n') goto yy92;
620 if (yych == '\r') goto yy98;
621 if (yych >= ' ') goto yy92;
625 if (yych == '$') goto yy94;
627 if (yych <= ':') goto yy92;
628 if (yych == '|') goto yy92;
636 eval->AddText(StringPiece(start, p - start));
648 eval->AddText(StringPiece(start, 1));
654 if ((yych = *p) <= '/') {
656 if (yych == '\n') goto yy110;
657 if (yych <= 0x1F) goto yy99;
661 if (yych <= '#') goto yy99;
664 if (yych == '-') goto yy105;
671 if (yych <= '9') goto yy105;
674 if (yych <= '@') goto yy99;
675 if (yych <= 'Z') goto yy105;
680 if (yych <= '_') goto yy105;
683 if (yych <= 'z') goto yy105;
684 if (yych <= '{') goto yy109;
692 return Error("lexing error", err);
698 return Error("unexpected EOF", err);
708 return Error("bad $-escape (literal $ must be written as $$)", err);
713 eval->AddText(StringPiece(" ", 1));
719 eval->AddText(StringPiece("$", 1));
728 eval->AddSpecial(StringPiece(start + 1, p - start - 1));
734 eval->AddText(StringPiece(":", 1));
739 if (yybm[0+yych] & 32) {
746 if (yybm[0+yych] & 16) {
755 if (yybm[0+yych] & 32) {
758 if (yych == '}') goto yy116;
764 eval->AddSpecial(StringPiece(start + 2, p - start - 3));
771 if (yybm[0+yych] & 64) {
779 if (yybm[0+yych] & 128) {
790 // Non-path strings end in newlines, so there's no whitespace to eat.