1 /* Generated by re2c 0.16 */
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* line_start = input_.str_;
27 for (const char* p = input_.str_; p < last_token_; ++p) {
33 int col = last_token_ ? (int)(last_token_ - line_start) : 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 (line_start[len] == 0 || line_start[len] == '\n') {
51 *err += string(line_start, 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, 128, 128, 128, 128, 128, 128, 128,
130 128, 128, 0, 128, 128, 128, 128, 128,
131 128, 128, 128, 128, 128, 128, 128, 128,
132 128, 128, 128, 128, 128, 128, 128, 128,
133 160, 128, 128, 128, 128, 128, 128, 128,
134 128, 128, 128, 128, 128, 192, 192, 128,
135 192, 192, 192, 192, 192, 192, 192, 192,
136 192, 192, 128, 128, 128, 128, 128, 128,
137 128, 192, 192, 192, 192, 192, 192, 192,
138 192, 192, 192, 192, 192, 192, 192, 192,
139 192, 192, 192, 192, 192, 192, 192, 192,
140 192, 192, 192, 128, 128, 128, 128, 192,
141 128, 192, 192, 192, 192, 192, 192, 192,
142 192, 192, 192, 192, 192, 192, 192, 192,
143 192, 192, 192, 192, 192, 192, 192, 192,
144 192, 192, 192, 128, 128, 128, 128, 128,
145 128, 128, 128, 128, 128, 128, 128, 128,
146 128, 128, 128, 128, 128, 128, 128, 128,
147 128, 128, 128, 128, 128, 128, 128, 128,
148 128, 128, 128, 128, 128, 128, 128, 128,
149 128, 128, 128, 128, 128, 128, 128, 128,
150 128, 128, 128, 128, 128, 128, 128, 128,
151 128, 128, 128, 128, 128, 128, 128, 128,
152 128, 128, 128, 128, 128, 128, 128, 128,
153 128, 128, 128, 128, 128, 128, 128, 128,
154 128, 128, 128, 128, 128, 128, 128, 128,
155 128, 128, 128, 128, 128, 128, 128, 128,
156 128, 128, 128, 128, 128, 128, 128, 128,
157 128, 128, 128, 128, 128, 128, 128, 128,
158 128, 128, 128, 128, 128, 128, 128, 128,
159 128, 128, 128, 128, 128, 128, 128, 128,
160 128, 128, 128, 128, 128, 128, 128, 128,
163 if (yybm[0+yych] & 32) {
169 if (yych <= 0x00) goto yy2;
170 if (yych == '\n') goto yy6;
173 if (yych <= '\r') goto yy8;
174 if (yych == '#') goto yy12;
179 if (yych == '/') goto yy4;
180 if (yych <= '9') goto yy13;
184 if (yych <= '<') goto yy4;
187 if (yych <= '@') goto yy4;
188 if (yych <= 'Z') goto yy13;
196 if (yych == '`') goto yy4;
197 if (yych <= 'a') goto yy13;
200 if (yych == 'd') goto yy21;
201 if (yych <= 'h') goto yy13;
206 if (yych == 'p') goto yy23;
207 if (yych <= 'q') goto yy13;
211 if (yych <= 's') goto yy25;
214 if (yych == '|') goto yy26;
222 { token = TEOF; break; }
226 { token = ERROR; break; }
229 { token = NEWLINE; break; }
232 if (yych == '\n') goto yy28;
238 if (yybm[0+yych] & 32) {
242 if (yych == '\n') goto yy6;
244 if (yych <= '\r') goto yy30;
245 if (yych == '#') goto yy32;
248 { token = INDENT; break; }
252 if (yych <= 0x00) goto yy5;
258 if (yybm[0+yych] & 64) {
261 { token = IDENT; break; }
264 { token = COLON; break; }
267 { token = EQUALS; break; }
270 if (yych == 'u') goto yy36;
274 if (yych == 'e') goto yy37;
278 if (yych == 'n') goto yy38;
282 if (yych == 'o') goto yy39;
286 if (yych == 'u') goto yy40;
290 if (yych == 'u') goto yy41;
294 if ((yych = *p) == '|') goto yy42;
295 { token = PIPE; break; }
298 { token = NEWLINE; break; }
301 if (yych == '\n') goto yy28;
313 if (yybm[0+yych] & 128) {
316 if (yych <= 0x00) goto yy31;
321 if (yych == 'i') goto yy44;
325 if (yych == 'f') goto yy45;
329 if (yych == 'c') goto yy46;
333 if (yych == 'o') goto yy47;
337 if (yych == 'l') goto yy48;
341 if (yych == 'b') goto yy49;
345 { token = PIPE2; break; }
348 if (yych == 'l') goto yy50;
352 if (yych == 'a') goto yy51;
356 if (yych == 'l') goto yy52;
360 if (yych == 'l') goto yy53;
364 if (yych == 'e') goto yy55;
368 if (yych == 'n') goto yy57;
372 if (yych == 'd') goto yy58;
376 if (yych == 'u') goto yy60;
380 if (yych == 'u') goto yy61;
384 if (yybm[0+(yych = *p)] & 64) {
387 { token = POOL; break; }
390 if (yybm[0+(yych = *p)] & 64) {
393 { token = RULE; break; }
396 if (yych == 'i') goto yy62;
400 if (yybm[0+(yych = *p)] & 64) {
403 { token = BUILD; break; }
406 if (yych == 'l') goto yy63;
410 if (yych == 'd') goto yy64;
414 if (yych == 'n') goto yy65;
418 if (yych == 't') goto yy66;
422 if (yych == 'e') goto yy68;
426 if (yych == 'j') goto yy70;
430 if (yybm[0+(yych = *p)] & 64) {
433 { token = DEFAULT; break; }
436 if (yybm[0+(yych = *p)] & 64) {
439 { token = INCLUDE; break; }
442 if (yych != 'a') goto yy14;
444 if (yybm[0+(yych = *p)] & 64) {
447 { token = SUBNINJA; break; }
454 if (token != NEWLINE && token != TEOF)
459 bool Lexer::PeekToken(Token token) {
460 Token t = ReadToken();
467 void Lexer::EatWhitespace() {
468 const char* p = ofs_;
475 static const unsigned char yybm[] = {
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 128, 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,
488 0, 0, 0, 0, 0, 0, 0, 0,
489 0, 0, 0, 0, 0, 0, 0, 0,
490 0, 0, 0, 0, 0, 0, 0, 0,
491 0, 0, 0, 0, 0, 0, 0, 0,
492 0, 0, 0, 0, 0, 0, 0, 0,
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, 0, 0, 0,
499 0, 0, 0, 0, 0, 0, 0, 0,
500 0, 0, 0, 0, 0, 0, 0, 0,
501 0, 0, 0, 0, 0, 0, 0, 0,
502 0, 0, 0, 0, 0, 0, 0, 0,
503 0, 0, 0, 0, 0, 0, 0, 0,
504 0, 0, 0, 0, 0, 0, 0, 0,
505 0, 0, 0, 0, 0, 0, 0, 0,
506 0, 0, 0, 0, 0, 0, 0, 0,
507 0, 0, 0, 0, 0, 0, 0, 0,
510 if (yybm[0+yych] & 128) {
513 if (yych <= 0x00) goto yy75;
514 if (yych == '$') goto yy82;
526 if (yybm[0+yych] & 128) {
532 if (yych == '\n') goto yy83;
533 if (yych == '\r') goto yy85;
540 if (yych == '\n') goto yy87;
551 bool Lexer::ReadIdent(string* out) {
552 const char* p = ofs_;
559 static const unsigned char yybm[] = {
560 0, 0, 0, 0, 0, 0, 0, 0,
561 0, 0, 0, 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, 128, 128, 0,
566 128, 128, 128, 128, 128, 128, 128, 128,
567 128, 128, 0, 0, 0, 0, 0, 0,
568 0, 128, 128, 128, 128, 128, 128, 128,
569 128, 128, 128, 128, 128, 128, 128, 128,
570 128, 128, 128, 128, 128, 128, 128, 128,
571 128, 128, 128, 0, 0, 0, 0, 128,
572 0, 128, 128, 128, 128, 128, 128, 128,
573 128, 128, 128, 128, 128, 128, 128, 128,
574 128, 128, 128, 128, 128, 128, 128, 128,
575 128, 128, 128, 0, 0, 0, 0, 0,
576 0, 0, 0, 0, 0, 0, 0, 0,
577 0, 0, 0, 0, 0, 0, 0, 0,
578 0, 0, 0, 0, 0, 0, 0, 0,
579 0, 0, 0, 0, 0, 0, 0, 0,
580 0, 0, 0, 0, 0, 0, 0, 0,
581 0, 0, 0, 0, 0, 0, 0, 0,
582 0, 0, 0, 0, 0, 0, 0, 0,
583 0, 0, 0, 0, 0, 0, 0, 0,
584 0, 0, 0, 0, 0, 0, 0, 0,
585 0, 0, 0, 0, 0, 0, 0, 0,
586 0, 0, 0, 0, 0, 0, 0, 0,
587 0, 0, 0, 0, 0, 0, 0, 0,
588 0, 0, 0, 0, 0, 0, 0, 0,
589 0, 0, 0, 0, 0, 0, 0, 0,
590 0, 0, 0, 0, 0, 0, 0, 0,
591 0, 0, 0, 0, 0, 0, 0, 0,
594 if (yybm[0+yych] & 128) {
605 if (yybm[0+yych] & 128) {
609 out->assign(start, p - start);
621 bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) {
622 const char* p = ofs_;
630 static const unsigned char yybm[] = {
631 0, 16, 16, 16, 16, 16, 16, 16,
632 16, 16, 0, 16, 16, 0, 16, 16,
633 16, 16, 16, 16, 16, 16, 16, 16,
634 16, 16, 16, 16, 16, 16, 16, 16,
635 32, 16, 16, 16, 0, 16, 16, 16,
636 16, 16, 16, 16, 16, 208, 144, 16,
637 208, 208, 208, 208, 208, 208, 208, 208,
638 208, 208, 0, 16, 16, 16, 16, 16,
639 16, 208, 208, 208, 208, 208, 208, 208,
640 208, 208, 208, 208, 208, 208, 208, 208,
641 208, 208, 208, 208, 208, 208, 208, 208,
642 208, 208, 208, 16, 16, 16, 16, 208,
643 16, 208, 208, 208, 208, 208, 208, 208,
644 208, 208, 208, 208, 208, 208, 208, 208,
645 208, 208, 208, 208, 208, 208, 208, 208,
646 208, 208, 208, 16, 0, 16, 16, 16,
647 16, 16, 16, 16, 16, 16, 16, 16,
648 16, 16, 16, 16, 16, 16, 16, 16,
649 16, 16, 16, 16, 16, 16, 16, 16,
650 16, 16, 16, 16, 16, 16, 16, 16,
651 16, 16, 16, 16, 16, 16, 16, 16,
652 16, 16, 16, 16, 16, 16, 16, 16,
653 16, 16, 16, 16, 16, 16, 16, 16,
654 16, 16, 16, 16, 16, 16, 16, 16,
655 16, 16, 16, 16, 16, 16, 16, 16,
656 16, 16, 16, 16, 16, 16, 16, 16,
657 16, 16, 16, 16, 16, 16, 16, 16,
658 16, 16, 16, 16, 16, 16, 16, 16,
659 16, 16, 16, 16, 16, 16, 16, 16,
660 16, 16, 16, 16, 16, 16, 16, 16,
661 16, 16, 16, 16, 16, 16, 16, 16,
662 16, 16, 16, 16, 16, 16, 16, 16,
665 if (yybm[0+yych] & 16) {
669 if (yych <= 0x00) goto yy98;
670 if (yych <= '\n') goto yy103;
673 if (yych <= ' ') goto yy103;
674 if (yych <= '$') goto yy107;
681 return Error("unexpected EOF", err);
686 if (yybm[0+yych] & 16) {
690 eval->AddText(StringPiece(start, p - start));
702 eval->AddText(StringPiece(start, 1));
708 if ((yych = *p) == '\n') goto yy108;
711 return Error(DescribeLastError(), err);
715 if (yybm[0+yych] & 64) {
720 if (yych == '\n') goto yy112;
723 if (yych <= '\r') goto yy115;
724 if (yych <= 0x1F) goto yy110;
729 if (yych == '$') goto yy118;
732 if (yych <= ':') goto yy123;
733 if (yych <= '`') goto yy110;
734 if (yych <= '{') goto yy125;
750 return Error("bad $-escape (literal $ must be written as $$)", err);
755 if (yybm[0+yych] & 32) {
763 if (yych == '\n') goto yy126;
768 eval->AddText(StringPiece(" ", 1));
774 eval->AddText(StringPiece("$", 1));
780 if (yybm[0+yych] & 64) {
784 eval->AddSpecial(StringPiece(start + 1, p - start - 1));
790 eval->AddText(StringPiece(":", 1));
795 if (yybm[0+yych] & 128) {
802 if (yych == ' ') goto yy126;
809 if (yybm[0+yych] & 128) {
812 if (yych == '}') goto yy132;
818 eval->AddSpecial(StringPiece(start + 2, p - start - 3));
828 // Non-path strings end in newlines, so there's no whitespace to eat.