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_ ? (int)(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 POOL: return "'pool'";
87 case RULE: return "'rule'";
88 case SUBNINJA: return "'subninja'";
89 case TEOF: return "eof";
91 return NULL; // not reached
94 const char* Lexer::TokenErrorHint(Token expected) {
97 return " ($ also escapes ':')";
103 string Lexer::DescribeLastError() {
105 switch (last_token_[0]) {
107 return "tabs are not allowed, use spaces";
110 return "lexing error";
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, 64, 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 yy23;
168 if (yych == '\n') goto yy7;
172 if (yych <= '\r') goto yy6;
175 if (yych <= ' ') goto yy2;
176 if (yych <= '"') goto yy25;
182 if (yych <= ',') goto yy25;
183 if (yych == '/') goto yy25;
187 if (yych <= ':') goto yy16;
190 if (yych <= '=') goto yy14;
191 if (yych <= '@') goto yy25;
199 if (yych == '_') goto yy22;
200 if (yych <= '`') goto yy25;
204 if (yych <= 'b') goto yy9;
207 if (yych <= 'd') goto yy13;
208 if (yych <= 'h') goto yy22;
214 if (yych == 'p') goto yy11;
215 if (yych <= 'q') goto yy22;
219 if (yych <= 's') goto yy21;
222 if (yych == '|') goto yy18;
233 { token = INDENT; break; }
237 if (yych >= 0x01) goto yy68;
239 { token = ERROR; break; }
242 if (yych == '\n') goto yy65;
247 { token = NEWLINE; break; }
250 if ((yych = *p) == 'u') goto yy60;
253 { token = IDENT; break; }
256 if (yych == 'o') goto yy56;
260 if (yych == 'u') goto yy52;
264 if (yych == 'e') goto yy45;
268 { token = EQUALS; break; }
271 { token = COLON; break; }
274 if ((yych = *p) == '|') goto yy43;
275 { token = PIPE; break; }
278 if (yych == 'n') goto yy36;
282 if (yych == 'u') goto yy28;
289 { token = TEOF; break; }
297 if (yybm[0+yych] & 32) {
303 if (yych != 'b') goto yy27;
305 if (yych != 'n') goto yy27;
307 if (yych != 'i') goto yy27;
309 if (yych != 'n') goto yy27;
311 if (yych != 'j') goto yy27;
313 if (yych != 'a') goto yy27;
315 if (yybm[0+(yych = *p)] & 32) {
318 { token = SUBNINJA; break; }
321 if (yych != 'c') goto yy27;
323 if (yych != 'l') goto yy27;
325 if (yych != 'u') goto yy27;
327 if (yych != 'd') goto yy27;
329 if (yych != 'e') goto yy27;
331 if (yybm[0+(yych = *p)] & 32) {
334 { token = INCLUDE; break; }
337 { token = PIPE2; break; }
340 if (yych != 'f') goto yy27;
342 if (yych != 'a') goto yy27;
344 if (yych != 'u') goto yy27;
346 if (yych != 'l') goto yy27;
348 if (yych != 't') goto yy27;
350 if (yybm[0+(yych = *p)] & 32) {
353 { token = DEFAULT; break; }
356 if (yych != 'l') goto yy27;
358 if (yych != 'e') goto yy27;
360 if (yybm[0+(yych = *p)] & 32) {
363 { token = RULE; break; }
366 if (yych != 'o') goto yy27;
368 if (yych != 'l') goto yy27;
370 if (yybm[0+(yych = *p)] & 32) {
373 { token = POOL; break; }
376 if (yych != 'i') goto yy27;
378 if (yych != 'l') goto yy27;
380 if (yych != 'd') goto yy27;
382 if (yybm[0+(yych = *p)] & 32) {
385 { token = BUILD; break; }
388 { token = NEWLINE; break; }
393 if (yybm[0+yych] & 64) {
396 if (yych >= 0x01) goto yy70;
412 if (yybm[0+yych] & 128) {
416 if (yych != '\n') goto yy3;
418 if (yych <= '\r') goto yy75;
419 if (yych == '#') goto yy67;
426 if ((yych = *p) == '\n') goto yy65;
434 if (token != NEWLINE && token != TEOF)
439 bool Lexer::PeekToken(Token token) {
440 Token t = ReadToken();
447 void Lexer::EatWhitespace() {
448 const char* p = ofs_;
455 static const unsigned char yybm[] = {
456 0, 0, 0, 0, 0, 0, 0, 0,
457 0, 0, 0, 0, 0, 0, 0, 0,
458 0, 0, 0, 0, 0, 0, 0, 0,
459 0, 0, 0, 0, 0, 0, 0, 0,
460 128, 0, 0, 0, 0, 0, 0, 0,
461 0, 0, 0, 0, 0, 0, 0, 0,
462 0, 0, 0, 0, 0, 0, 0, 0,
463 0, 0, 0, 0, 0, 0, 0, 0,
464 0, 0, 0, 0, 0, 0, 0, 0,
465 0, 0, 0, 0, 0, 0, 0, 0,
466 0, 0, 0, 0, 0, 0, 0, 0,
467 0, 0, 0, 0, 0, 0, 0, 0,
468 0, 0, 0, 0, 0, 0, 0, 0,
469 0, 0, 0, 0, 0, 0, 0, 0,
470 0, 0, 0, 0, 0, 0, 0, 0,
471 0, 0, 0, 0, 0, 0, 0, 0,
472 0, 0, 0, 0, 0, 0, 0, 0,
473 0, 0, 0, 0, 0, 0, 0, 0,
474 0, 0, 0, 0, 0, 0, 0, 0,
475 0, 0, 0, 0, 0, 0, 0, 0,
476 0, 0, 0, 0, 0, 0, 0, 0,
477 0, 0, 0, 0, 0, 0, 0, 0,
478 0, 0, 0, 0, 0, 0, 0, 0,
479 0, 0, 0, 0, 0, 0, 0, 0,
480 0, 0, 0, 0, 0, 0, 0, 0,
481 0, 0, 0, 0, 0, 0, 0, 0,
482 0, 0, 0, 0, 0, 0, 0, 0,
483 0, 0, 0, 0, 0, 0, 0, 0,
484 0, 0, 0, 0, 0, 0, 0, 0,
485 0, 0, 0, 0, 0, 0, 0, 0,
486 0, 0, 0, 0, 0, 0, 0, 0,
487 0, 0, 0, 0, 0, 0, 0, 0,
491 if (yych <= 0x00) goto yy82;
492 if (yych <= 0x1F) goto yy84;
494 if (yych == '$') goto yy80;
504 if (yych == '\n') goto yy85;
505 if (yych == '\r') goto yy87;
519 if (yych == '\n') goto yy89;
529 if (yybm[0+yych] & 128) {
538 bool Lexer::ReadIdent(string* out) {
539 const char* p = ofs_;
541 const char* start = p;
545 static const unsigned char yybm[] = {
546 0, 0, 0, 0, 0, 0, 0, 0,
547 0, 0, 0, 0, 0, 0, 0, 0,
548 0, 0, 0, 0, 0, 0, 0, 0,
549 0, 0, 0, 0, 0, 0, 0, 0,
550 0, 0, 0, 0, 0, 0, 0, 0,
551 0, 0, 0, 0, 0, 128, 128, 0,
552 128, 128, 128, 128, 128, 128, 128, 128,
553 128, 128, 0, 0, 0, 0, 0, 0,
554 0, 128, 128, 128, 128, 128, 128, 128,
555 128, 128, 128, 128, 128, 128, 128, 128,
556 128, 128, 128, 128, 128, 128, 128, 128,
557 128, 128, 128, 0, 0, 0, 0, 128,
558 0, 128, 128, 128, 128, 128, 128, 128,
559 128, 128, 128, 128, 128, 128, 128, 128,
560 128, 128, 128, 128, 128, 128, 128, 128,
561 128, 128, 128, 0, 0, 0, 0, 0,
562 0, 0, 0, 0, 0, 0, 0, 0,
563 0, 0, 0, 0, 0, 0, 0, 0,
564 0, 0, 0, 0, 0, 0, 0, 0,
565 0, 0, 0, 0, 0, 0, 0, 0,
566 0, 0, 0, 0, 0, 0, 0, 0,
567 0, 0, 0, 0, 0, 0, 0, 0,
568 0, 0, 0, 0, 0, 0, 0, 0,
569 0, 0, 0, 0, 0, 0, 0, 0,
570 0, 0, 0, 0, 0, 0, 0, 0,
571 0, 0, 0, 0, 0, 0, 0, 0,
572 0, 0, 0, 0, 0, 0, 0, 0,
573 0, 0, 0, 0, 0, 0, 0, 0,
574 0, 0, 0, 0, 0, 0, 0, 0,
575 0, 0, 0, 0, 0, 0, 0, 0,
576 0, 0, 0, 0, 0, 0, 0, 0,
577 0, 0, 0, 0, 0, 0, 0, 0,
582 if (yych <= ',') goto yy97;
584 if (yych <= '/') goto yy97;
585 if (yych >= ':') goto yy97;
589 if (yych <= 'Z') goto yy95;
590 if (yych <= '^') goto yy97;
592 if (yych <= '`') goto yy97;
593 if (yych >= '{') goto yy97;
602 out->assign(start, p - start);
612 if (yybm[0+yych] & 128) {
624 bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) {
625 const char* p = ofs_;
633 static const unsigned char yybm[] = {
634 0, 128, 128, 128, 128, 128, 128, 128,
635 128, 128, 0, 128, 128, 0, 128, 128,
636 128, 128, 128, 128, 128, 128, 128, 128,
637 128, 128, 128, 128, 128, 128, 128, 128,
638 16, 128, 128, 128, 0, 128, 128, 128,
639 128, 128, 128, 128, 128, 224, 160, 128,
640 224, 224, 224, 224, 224, 224, 224, 224,
641 224, 224, 0, 128, 128, 128, 128, 128,
642 128, 224, 224, 224, 224, 224, 224, 224,
643 224, 224, 224, 224, 224, 224, 224, 224,
644 224, 224, 224, 224, 224, 224, 224, 224,
645 224, 224, 224, 128, 128, 128, 128, 224,
646 128, 224, 224, 224, 224, 224, 224, 224,
647 224, 224, 224, 224, 224, 224, 224, 224,
648 224, 224, 224, 224, 224, 224, 224, 224,
649 224, 224, 224, 128, 0, 128, 128, 128,
650 128, 128, 128, 128, 128, 128, 128, 128,
651 128, 128, 128, 128, 128, 128, 128, 128,
652 128, 128, 128, 128, 128, 128, 128, 128,
653 128, 128, 128, 128, 128, 128, 128, 128,
654 128, 128, 128, 128, 128, 128, 128, 128,
655 128, 128, 128, 128, 128, 128, 128, 128,
656 128, 128, 128, 128, 128, 128, 128, 128,
657 128, 128, 128, 128, 128, 128, 128, 128,
658 128, 128, 128, 128, 128, 128, 128, 128,
659 128, 128, 128, 128, 128, 128, 128, 128,
660 128, 128, 128, 128, 128, 128, 128, 128,
661 128, 128, 128, 128, 128, 128, 128, 128,
662 128, 128, 128, 128, 128, 128, 128, 128,
663 128, 128, 128, 128, 128, 128, 128, 128,
664 128, 128, 128, 128, 128, 128, 128, 128,
665 128, 128, 128, 128, 128, 128, 128, 128,
670 if (yych <= 0x00) goto yy110;
671 if (yych >= '\n') goto yy107;
673 if (yych == '\r') goto yy105;
674 if (yych >= ' ') goto yy107;
678 if (yych == '$') goto yy109;
680 if (yych <= ':') goto yy107;
681 if (yych == '|') goto yy107;
689 eval->AddText(StringPiece(start, p - start));
694 if ((yych = *p) == '\n') goto yy137;
697 return Error(DescribeLastError(), err);
708 eval->AddText(StringPiece(start, 1));
717 if (yych <= '\t') goto yy112;
720 if (yych == '\r') goto yy114;
725 if (yych <= ' ') goto yy115;
728 if (yych <= '$') goto yy117;
729 if (yych <= ',') goto yy112;
736 if (yych <= '/') goto yy112;
739 if (yych <= ':') goto yy121;
740 if (yych <= '@') goto yy112;
745 if (yych == '_') goto yy119;
748 if (yych <= 'z') goto yy119;
749 if (yych <= '{') goto yy123;
758 return Error("unexpected EOF", err);
765 return Error("bad $-escape (literal $ must be written as $$)", err);
769 if (yych == '\n') goto yy134;
774 eval->AddText(StringPiece(" ", 1));
780 eval->AddText(StringPiece("$", 1));
789 eval->AddSpecial(StringPiece(start + 1, p - start - 1));
795 eval->AddText(StringPiece(":", 1));
800 if (yybm[0+yych] & 32) {
807 if (yybm[0+yych] & 16) {
816 if (yybm[0+yych] & 32) {
819 if (yych == '}') goto yy130;
825 eval->AddSpecial(StringPiece(start + 2, p - start - 3));
832 if (yybm[0+yych] & 64) {
839 if (yych == ' ') goto yy134;
854 if (yybm[0+yych] & 128) {
865 // Non-path strings end in newlines, so there's no whitespace to eat.