Ninja
lexer.cc
Go to the documentation of this file.
1/* Generated by re2c */
2// Copyright 2011 Google Inc. All Rights Reserved.
3//
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
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
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.
15
16#include "lexer.h"
17
18#include <stdio.h>
19
20#include "eval_env.h"
21#include "util.h"
22
23using namespace std;
24
25bool Lexer::Error(const string& message, string* err) {
26 // Compute line/column.
27 int line = 1;
28 const char* line_start = input_.str_;
29 for (const char* p = input_.str_; p < last_token_; ++p) {
30 if (*p == '\n') {
31 ++line;
32 line_start = p + 1;
33 }
34 }
35 int col = last_token_ ? (int)(last_token_ - line_start) : 0;
36
37 char buf[1024];
38 snprintf(buf, sizeof(buf), "%s:%d: ", filename_.AsString().c_str(), line);
39 *err = buf;
40 *err += message + "\n";
41
42 // Add some context to the message.
43 const int kTruncateColumn = 72;
44 if (col > 0 && col < kTruncateColumn) {
45 int len;
46 bool truncated = true;
47 for (len = 0; len < kTruncateColumn; ++len) {
48 if (line_start[len] == 0 || line_start[len] == '\n') {
49 truncated = false;
50 break;
51 }
52 }
53 *err += string(line_start, len);
54 if (truncated)
55 *err += "...";
56 *err += "\n";
57 *err += string(col, ' ');
58 *err += "^ near here";
59 }
60
61 return false;
62}
63
64Lexer::Lexer(const char* input) {
65 Start("input", input);
66}
67
68void Lexer::Start(StringPiece filename, StringPiece input) {
69 filename_ = filename;
70 input_ = input;
71 ofs_ = input_.str_;
72 last_token_ = NULL;
73}
74
75const char* Lexer::TokenName(Token t) {
76 switch (t) {
77 case ERROR: return "lexing error";
78 case BUILD: return "'build'";
79 case COLON: return "':'";
80 case DEFAULT: return "'default'";
81 case EQUALS: return "'='";
82 case IDENT: return "identifier";
83 case INCLUDE: return "'include'";
84 case INDENT: return "indent";
85 case NEWLINE: return "newline";
86 case PIPE2: return "'||'";
87 case PIPE: return "'|'";
88 case PIPEAT: return "'|@'";
89 case POOL: return "'pool'";
90 case RULE: return "'rule'";
91 case SUBNINJA: return "'subninja'";
92 case TEOF: return "eof";
93 }
94 return NULL; // not reached
95}
96
97const char* Lexer::TokenErrorHint(Token expected) {
98 switch (expected) {
99 case COLON:
100 return " ($ also escapes ':')";
101 default:
102 return "";
103 }
104}
105
107 if (last_token_) {
108 switch (last_token_[0]) {
109 case '\t':
110 return "tabs are not allowed, use spaces";
111 }
112 }
113 return "lexing error";
114}
115
119
121 const char* p = ofs_;
122 const char* q;
123 const char* start;
124 Lexer::Token token;
125 for (;;) {
126 start = p;
127
128{
129 unsigned char yych;
130 unsigned int yyaccept = 0;
131 static const unsigned char yybm[] = {
132 0, 128, 128, 128, 128, 128, 128, 128,
133 128, 128, 0, 128, 128, 128, 128, 128,
134 128, 128, 128, 128, 128, 128, 128, 128,
135 128, 128, 128, 128, 128, 128, 128, 128,
136 160, 128, 128, 128, 128, 128, 128, 128,
137 128, 128, 128, 128, 128, 192, 192, 128,
138 192, 192, 192, 192, 192, 192, 192, 192,
139 192, 192, 128, 128, 128, 128, 128, 128,
140 128, 192, 192, 192, 192, 192, 192, 192,
141 192, 192, 192, 192, 192, 192, 192, 192,
142 192, 192, 192, 192, 192, 192, 192, 192,
143 192, 192, 192, 128, 128, 128, 128, 192,
144 128, 192, 192, 192, 192, 192, 192, 192,
145 192, 192, 192, 192, 192, 192, 192, 192,
146 192, 192, 192, 192, 192, 192, 192, 192,
147 192, 192, 192, 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,
161 128, 128, 128, 128, 128, 128, 128, 128,
162 128, 128, 128, 128, 128, 128, 128, 128,
163 128, 128, 128, 128, 128, 128, 128, 128,
164 };
165 yych = *p;
166 if (yybm[0+yych] & 32) {
167 goto yy6;
168 }
169 if (yych <= '^') {
170 if (yych <= ',') {
171 if (yych <= '\f') {
172 if (yych <= 0x00) goto yy1;
173 if (yych == '\n') goto yy4;
174 goto yy2;
175 } else {
176 if (yych <= '\r') goto yy5;
177 if (yych == '#') goto yy8;
178 goto yy2;
179 }
180 } else {
181 if (yych <= ':') {
182 if (yych == '/') goto yy2;
183 if (yych <= '9') goto yy9;
184 goto yy11;
185 } else {
186 if (yych <= '=') {
187 if (yych <= '<') goto yy2;
188 goto yy12;
189 } else {
190 if (yych <= '@') goto yy2;
191 if (yych <= 'Z') goto yy9;
192 goto yy2;
193 }
194 }
195 }
196 } else {
197 if (yych <= 'i') {
198 if (yych <= 'b') {
199 if (yych == '`') goto yy2;
200 if (yych <= 'a') goto yy9;
201 goto yy13;
202 } else {
203 if (yych == 'd') goto yy14;
204 if (yych <= 'h') goto yy9;
205 goto yy15;
206 }
207 } else {
208 if (yych <= 'r') {
209 if (yych == 'p') goto yy16;
210 if (yych <= 'q') goto yy9;
211 goto yy17;
212 } else {
213 if (yych <= 'z') {
214 if (yych <= 's') goto yy18;
215 goto yy9;
216 } else {
217 if (yych == '|') goto yy19;
218 goto yy2;
219 }
220 }
221 }
222 }
223yy1:
224 ++p;
225 { token = TEOF; break; }
226yy2:
227 ++p;
228yy3:
229 { token = ERROR; break; }
230yy4:
231 ++p;
232 { token = NEWLINE; break; }
233yy5:
234 yych = *++p;
235 if (yych == '\n') goto yy20;
236 goto yy3;
237yy6:
238 yyaccept = 0;
239 yych = *(q = ++p);
240 if (yybm[0+yych] & 32) {
241 goto yy6;
242 }
243 if (yych <= '\f') {
244 if (yych == '\n') goto yy4;
245 } else {
246 if (yych <= '\r') goto yy21;
247 if (yych == '#') goto yy23;
248 }
249yy7:
250 { token = INDENT; break; }
251yy8:
252 yyaccept = 1;
253 yych = *(q = ++p);
254 if (yych <= 0x00) goto yy3;
255 goto yy24;
256yy9:
257 yych = *++p;
258yy10:
259 if (yybm[0+yych] & 64) {
260 goto yy9;
261 }
262 { token = IDENT; break; }
263yy11:
264 ++p;
265 { token = COLON; break; }
266yy12:
267 ++p;
268 { token = EQUALS; break; }
269yy13:
270 yych = *++p;
271 if (yych == 'u') goto yy25;
272 goto yy10;
273yy14:
274 yych = *++p;
275 if (yych == 'e') goto yy26;
276 goto yy10;
277yy15:
278 yych = *++p;
279 if (yych == 'n') goto yy27;
280 goto yy10;
281yy16:
282 yych = *++p;
283 if (yych == 'o') goto yy28;
284 goto yy10;
285yy17:
286 yych = *++p;
287 if (yych == 'u') goto yy29;
288 goto yy10;
289yy18:
290 yych = *++p;
291 if (yych == 'u') goto yy30;
292 goto yy10;
293yy19:
294 yych = *++p;
295 if (yych == '@') goto yy31;
296 if (yych == '|') goto yy32;
297 { token = PIPE; break; }
298yy20:
299 ++p;
300 { token = NEWLINE; break; }
301yy21:
302 yych = *++p;
303 if (yych == '\n') goto yy20;
304yy22:
305 p = q;
306 if (yyaccept == 0) {
307 goto yy7;
308 } else {
309 goto yy3;
310 }
311yy23:
312 yych = *++p;
313yy24:
314 if (yybm[0+yych] & 128) {
315 goto yy23;
316 }
317 if (yych <= 0x00) goto yy22;
318 ++p;
319 { continue; }
320yy25:
321 yych = *++p;
322 if (yych == 'i') goto yy33;
323 goto yy10;
324yy26:
325 yych = *++p;
326 if (yych == 'f') goto yy34;
327 goto yy10;
328yy27:
329 yych = *++p;
330 if (yych == 'c') goto yy35;
331 goto yy10;
332yy28:
333 yych = *++p;
334 if (yych == 'o') goto yy36;
335 goto yy10;
336yy29:
337 yych = *++p;
338 if (yych == 'l') goto yy37;
339 goto yy10;
340yy30:
341 yych = *++p;
342 if (yych == 'b') goto yy38;
343 goto yy10;
344yy31:
345 ++p;
346 { token = PIPEAT; break; }
347yy32:
348 ++p;
349 { token = PIPE2; break; }
350yy33:
351 yych = *++p;
352 if (yych == 'l') goto yy39;
353 goto yy10;
354yy34:
355 yych = *++p;
356 if (yych == 'a') goto yy40;
357 goto yy10;
358yy35:
359 yych = *++p;
360 if (yych == 'l') goto yy41;
361 goto yy10;
362yy36:
363 yych = *++p;
364 if (yych == 'l') goto yy42;
365 goto yy10;
366yy37:
367 yych = *++p;
368 if (yych == 'e') goto yy43;
369 goto yy10;
370yy38:
371 yych = *++p;
372 if (yych == 'n') goto yy44;
373 goto yy10;
374yy39:
375 yych = *++p;
376 if (yych == 'd') goto yy45;
377 goto yy10;
378yy40:
379 yych = *++p;
380 if (yych == 'u') goto yy46;
381 goto yy10;
382yy41:
383 yych = *++p;
384 if (yych == 'u') goto yy47;
385 goto yy10;
386yy42:
387 yych = *++p;
388 if (yybm[0+yych] & 64) {
389 goto yy9;
390 }
391 { token = POOL; break; }
392yy43:
393 yych = *++p;
394 if (yybm[0+yych] & 64) {
395 goto yy9;
396 }
397 { token = RULE; break; }
398yy44:
399 yych = *++p;
400 if (yych == 'i') goto yy48;
401 goto yy10;
402yy45:
403 yych = *++p;
404 if (yybm[0+yych] & 64) {
405 goto yy9;
406 }
407 { token = BUILD; break; }
408yy46:
409 yych = *++p;
410 if (yych == 'l') goto yy49;
411 goto yy10;
412yy47:
413 yych = *++p;
414 if (yych == 'd') goto yy50;
415 goto yy10;
416yy48:
417 yych = *++p;
418 if (yych == 'n') goto yy51;
419 goto yy10;
420yy49:
421 yych = *++p;
422 if (yych == 't') goto yy52;
423 goto yy10;
424yy50:
425 yych = *++p;
426 if (yych == 'e') goto yy53;
427 goto yy10;
428yy51:
429 yych = *++p;
430 if (yych == 'j') goto yy54;
431 goto yy10;
432yy52:
433 yych = *++p;
434 if (yybm[0+yych] & 64) {
435 goto yy9;
436 }
437 { token = DEFAULT; break; }
438yy53:
439 yych = *++p;
440 if (yybm[0+yych] & 64) {
441 goto yy9;
442 }
443 { token = INCLUDE; break; }
444yy54:
445 yych = *++p;
446 if (yych != 'a') goto yy10;
447 yych = *++p;
448 if (yybm[0+yych] & 64) {
449 goto yy9;
450 }
451 { token = SUBNINJA; break; }
452}
453
454 }
455
456 last_token_ = start;
457 ofs_ = p;
458 if (token != NEWLINE && token != TEOF)
460 return token;
461}
462
464 Token t = ReadToken();
465 if (t == token)
466 return true;
467 UnreadToken();
468 return false;
469}
470
472 const char* p = ofs_;
473 const char* q;
474 for (;;) {
475 ofs_ = p;
476
477{
478 unsigned char yych;
479 static const unsigned char yybm[] = {
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 128, 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,
508 0, 0, 0, 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 };
513 yych = *p;
514 if (yybm[0+yych] & 128) {
515 goto yy59;
516 }
517 if (yych <= 0x00) goto yy56;
518 if (yych == '$') goto yy60;
519 goto yy57;
520yy56:
521 ++p;
522 { break; }
523yy57:
524 ++p;
525yy58:
526 { break; }
527yy59:
528 yych = *++p;
529 if (yybm[0+yych] & 128) {
530 goto yy59;
531 }
532 { continue; }
533yy60:
534 yych = *(q = ++p);
535 if (yych == '\n') goto yy61;
536 if (yych == '\r') goto yy62;
537 goto yy58;
538yy61:
539 ++p;
540 { continue; }
541yy62:
542 yych = *++p;
543 if (yych == '\n') goto yy63;
544 p = q;
545 goto yy58;
546yy63:
547 ++p;
548 { continue; }
549}
550
551 }
552}
553
554bool Lexer::ReadIdent(string* out) {
555 const char* p = ofs_;
556 const char* start;
557 for (;;) {
558 start = p;
559
560{
561 unsigned char yych;
562 static const unsigned char yybm[] = {
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, 128, 128, 0,
569 128, 128, 128, 128, 128, 128, 128, 128,
570 128, 128, 0, 0, 0, 0, 0, 0,
571 0, 128, 128, 128, 128, 128, 128, 128,
572 128, 128, 128, 128, 128, 128, 128, 128,
573 128, 128, 128, 128, 128, 128, 128, 128,
574 128, 128, 128, 0, 0, 0, 0, 128,
575 0, 128, 128, 128, 128, 128, 128, 128,
576 128, 128, 128, 128, 128, 128, 128, 128,
577 128, 128, 128, 128, 128, 128, 128, 128,
578 128, 128, 128, 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,
592 0, 0, 0, 0, 0, 0, 0, 0,
593 0, 0, 0, 0, 0, 0, 0, 0,
594 0, 0, 0, 0, 0, 0, 0, 0,
595 };
596 yych = *p;
597 if (yybm[0+yych] & 128) {
598 goto yy65;
599 }
600 ++p;
601 {
602 last_token_ = start;
603 return false;
604 }
605yy65:
606 yych = *++p;
607 if (yybm[0+yych] & 128) {
608 goto yy65;
609 }
610 {
611 out->assign(start, p - start);
612 break;
613 }
614}
615
616 }
617 last_token_ = start;
618 ofs_ = p;
620 return true;
621}
622
623bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) {
624 const char* p = ofs_;
625 const char* q;
626 const char* start;
627 for (;;) {
628 start = p;
629
630{
631 unsigned char yych;
632 static const unsigned char yybm[] = {
633 0, 16, 16, 16, 16, 16, 16, 16,
634 16, 16, 0, 16, 16, 0, 16, 16,
635 16, 16, 16, 16, 16, 16, 16, 16,
636 16, 16, 16, 16, 16, 16, 16, 16,
637 32, 16, 16, 16, 0, 16, 16, 16,
638 16, 16, 16, 16, 16, 208, 144, 16,
639 208, 208, 208, 208, 208, 208, 208, 208,
640 208, 208, 0, 16, 16, 16, 16, 16,
641 16, 208, 208, 208, 208, 208, 208, 208,
642 208, 208, 208, 208, 208, 208, 208, 208,
643 208, 208, 208, 208, 208, 208, 208, 208,
644 208, 208, 208, 16, 16, 16, 16, 208,
645 16, 208, 208, 208, 208, 208, 208, 208,
646 208, 208, 208, 208, 208, 208, 208, 208,
647 208, 208, 208, 208, 208, 208, 208, 208,
648 208, 208, 208, 16, 0, 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,
663 16, 16, 16, 16, 16, 16, 16, 16,
664 16, 16, 16, 16, 16, 16, 16, 16,
665 };
666 yych = *p;
667 if (yybm[0+yych] & 16) {
668 goto yy68;
669 }
670 if (yych <= '\r') {
671 if (yych <= 0x00) goto yy67;
672 if (yych <= '\n') goto yy69;
673 goto yy70;
674 } else {
675 if (yych <= ' ') goto yy69;
676 if (yych <= '$') goto yy71;
677 goto yy69;
678 }
679yy67:
680 ++p;
681 {
682 last_token_ = start;
683 return Error("unexpected EOF", err);
684 }
685yy68:
686 yych = *++p;
687 if (yybm[0+yych] & 16) {
688 goto yy68;
689 }
690 {
691 eval->AddText(StringPiece(start, p - start));
692 continue;
693 }
694yy69:
695 ++p;
696 {
697 if (path) {
698 p = start;
699 break;
700 } else {
701 if (*start == '\n')
702 break;
703 eval->AddText(StringPiece(start, 1));
704 continue;
705 }
706 }
707yy70:
708 yych = *++p;
709 if (yych == '\n') goto yy72;
710 {
711 last_token_ = start;
712 return Error(DescribeLastError(), err);
713 }
714yy71:
715 yych = *++p;
716 if (yybm[0+yych] & 64) {
717 goto yy79;
718 }
719 if (yych <= ' ') {
720 if (yych <= '\f') {
721 if (yych == '\n') goto yy75;
722 goto yy73;
723 } else {
724 if (yych <= '\r') goto yy76;
725 if (yych <= 0x1F) goto yy73;
726 goto yy77;
727 }
728 } else {
729 if (yych <= '/') {
730 if (yych == '$') goto yy78;
731 goto yy73;
732 } else {
733 if (yych <= ':') goto yy80;
734 if (yych <= '`') goto yy73;
735 if (yych <= '{') goto yy81;
736 goto yy73;
737 }
738 }
739yy72:
740 ++p;
741 {
742 if (path)
743 p = start;
744 break;
745 }
746yy73:
747 ++p;
748yy74:
749 {
750 last_token_ = start;
751 return Error("bad $-escape (literal $ must be written as $$)", err);
752 }
753yy75:
754 yych = *++p;
755 if (yybm[0+yych] & 32) {
756 goto yy75;
757 }
758 {
759 continue;
760 }
761yy76:
762 yych = *++p;
763 if (yych == '\n') goto yy82;
764 goto yy74;
765yy77:
766 ++p;
767 {
768 eval->AddText(StringPiece(" ", 1));
769 continue;
770 }
771yy78:
772 ++p;
773 {
774 eval->AddText(StringPiece("$", 1));
775 continue;
776 }
777yy79:
778 yych = *++p;
779 if (yybm[0+yych] & 64) {
780 goto yy79;
781 }
782 {
783 eval->AddSpecial(StringPiece(start + 1, p - start - 1));
784 continue;
785 }
786yy80:
787 ++p;
788 {
789 eval->AddText(StringPiece(":", 1));
790 continue;
791 }
792yy81:
793 yych = *(q = ++p);
794 if (yybm[0+yych] & 128) {
795 goto yy83;
796 }
797 goto yy74;
798yy82:
799 yych = *++p;
800 if (yych == ' ') goto yy82;
801 {
802 continue;
803 }
804yy83:
805 yych = *++p;
806 if (yybm[0+yych] & 128) {
807 goto yy83;
808 }
809 if (yych == '}') goto yy84;
810 p = q;
811 goto yy74;
812yy84:
813 ++p;
814 {
815 eval->AddSpecial(StringPiece(start + 2, p - start - 3));
816 continue;
817 }
818}
819
820 }
821 last_token_ = start;
822 ofs_ = p;
823 if (path)
825 // Non-path strings end in newlines, so there's no whitespace to eat.
826 return true;
827}
Definition hash_map.h:26
A tokenized string that contains variable references.
Definition eval_env.h:35
void AddSpecial(StringPiece text)
Definition eval_env.cc:136
void AddText(StringPiece text)
Definition eval_env.cc:126
static const char * TokenName(Token t)
Return a human-readable form of a token, used in error messages.
Definition lexer.cc:75
Token
Definition lexer.h:32
@ TEOF
Definition lexer.h:48
@ COLON
Definition lexer.h:35
@ NEWLINE
Definition lexer.h:41
@ POOL
Definition lexer.h:45
@ DEFAULT
Definition lexer.h:36
@ RULE
Definition lexer.h:46
@ INDENT
Definition lexer.h:40
@ ERROR
Definition lexer.h:33
@ INCLUDE
Definition lexer.h:39
@ PIPE
Definition lexer.h:42
@ EQUALS
Definition lexer.h:37
@ BUILD
Definition lexer.h:34
@ IDENT
Definition lexer.h:38
@ PIPE2
Definition lexer.h:43
@ SUBNINJA
Definition lexer.h:47
@ PIPEAT
Definition lexer.h:44
bool PeekToken(Token token)
If the next token is token, read it and return true.
Definition lexer.cc:463
Lexer()
Definition lexer.h:28
std::string DescribeLastError()
If the last token read was an ERROR token, provide more info or the empty string.
Definition lexer.cc:106
const char * ofs_
Definition lexer.h:102
void UnreadToken()
Rewind to the last read Token.
Definition lexer.cc:116
bool ReadEvalString(EvalString *eval, bool path, std::string *err)
Read a $-escaped string.
Definition lexer.cc:623
const char * last_token_
Definition lexer.h:103
void Start(StringPiece filename, StringPiece input)
Start parsing some input.
Definition lexer.cc:68
Token ReadToken()
Read a Token from the Token enum.
Definition lexer.cc:120
static const char * TokenErrorHint(Token expected)
Return a human-readable token hint, used in error messages.
Definition lexer.cc:97
StringPiece filename_
Definition lexer.h:100
void EatWhitespace()
Skip past whitespace (called after each read token/ident/etc.).
Definition lexer.cc:471
bool ReadIdent(std::string *out)
Read a simple identifier (a rule or variable name).
Definition lexer.cc:554
StringPiece input_
Definition lexer.h:101
bool Error(const std::string &message, std::string *err)
Construct an error message with context.
Definition lexer.cc:25
StringPiece represents a slice of a string whose memory is managed externally.