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 
23 using namespace std;
24 
25 bool 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 
64 Lexer::Lexer(const char* input) {
65  Start("input", input);
66 }
67 
68 void Lexer::Start(StringPiece filename, StringPiece input) {
69  filename_ = filename;
70  input_ = input;
71  ofs_ = input_.str_;
72  last_token_ = NULL;
73 }
74 
75 const 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 
97 const 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 
117  ofs_ = last_token_;
118 }
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 yy9;
168  }
169  if (yych <= '^') {
170  if (yych <= ',') {
171  if (yych <= '\f') {
172  if (yych <= 0x00) goto yy2;
173  if (yych == '\n') goto yy6;
174  goto yy4;
175  } else {
176  if (yych <= '\r') goto yy8;
177  if (yych == '#') goto yy12;
178  goto yy4;
179  }
180  } else {
181  if (yych <= ':') {
182  if (yych == '/') goto yy4;
183  if (yych <= '9') goto yy13;
184  goto yy16;
185  } else {
186  if (yych <= '=') {
187  if (yych <= '<') goto yy4;
188  goto yy18;
189  } else {
190  if (yych <= '@') goto yy4;
191  if (yych <= 'Z') goto yy13;
192  goto yy4;
193  }
194  }
195  }
196  } else {
197  if (yych <= 'i') {
198  if (yych <= 'b') {
199  if (yych == '`') goto yy4;
200  if (yych <= 'a') goto yy13;
201  goto yy20;
202  } else {
203  if (yych == 'd') goto yy21;
204  if (yych <= 'h') goto yy13;
205  goto yy22;
206  }
207  } else {
208  if (yych <= 'r') {
209  if (yych == 'p') goto yy23;
210  if (yych <= 'q') goto yy13;
211  goto yy24;
212  } else {
213  if (yych <= 'z') {
214  if (yych <= 's') goto yy25;
215  goto yy13;
216  } else {
217  if (yych == '|') goto yy26;
218  goto yy4;
219  }
220  }
221  }
222  }
223 yy2:
224  ++p;
225  { token = TEOF; break; }
226 yy4:
227  ++p;
228 yy5:
229  { token = ERROR; break; }
230 yy6:
231  ++p;
232  { token = NEWLINE; break; }
233 yy8:
234  yych = *++p;
235  if (yych == '\n') goto yy28;
236  goto yy5;
237 yy9:
238  yyaccept = 0;
239  yych = *(q = ++p);
240  if (yybm[0+yych] & 32) {
241  goto yy9;
242  }
243  if (yych <= '\f') {
244  if (yych == '\n') goto yy6;
245  } else {
246  if (yych <= '\r') goto yy30;
247  if (yych == '#') goto yy32;
248  }
249 yy11:
250  { token = INDENT; break; }
251 yy12:
252  yyaccept = 1;
253  yych = *(q = ++p);
254  if (yych <= 0x00) goto yy5;
255  goto yy33;
256 yy13:
257  yych = *++p;
258 yy14:
259  if (yybm[0+yych] & 64) {
260  goto yy13;
261  }
262  { token = IDENT; break; }
263 yy16:
264  ++p;
265  { token = COLON; break; }
266 yy18:
267  ++p;
268  { token = EQUALS; break; }
269 yy20:
270  yych = *++p;
271  if (yych == 'u') goto yy36;
272  goto yy14;
273 yy21:
274  yych = *++p;
275  if (yych == 'e') goto yy37;
276  goto yy14;
277 yy22:
278  yych = *++p;
279  if (yych == 'n') goto yy38;
280  goto yy14;
281 yy23:
282  yych = *++p;
283  if (yych == 'o') goto yy39;
284  goto yy14;
285 yy24:
286  yych = *++p;
287  if (yych == 'u') goto yy40;
288  goto yy14;
289 yy25:
290  yych = *++p;
291  if (yych == 'u') goto yy41;
292  goto yy14;
293 yy26:
294  yych = *++p;
295  if (yych == '@') goto yy42;
296  if (yych == '|') goto yy44;
297  { token = PIPE; break; }
298 yy28:
299  ++p;
300  { token = NEWLINE; break; }
301 yy30:
302  yych = *++p;
303  if (yych == '\n') goto yy28;
304 yy31:
305  p = q;
306  if (yyaccept == 0) {
307  goto yy11;
308  } else {
309  goto yy5;
310  }
311 yy32:
312  yych = *++p;
313 yy33:
314  if (yybm[0+yych] & 128) {
315  goto yy32;
316  }
317  if (yych <= 0x00) goto yy31;
318  ++p;
319  { continue; }
320 yy36:
321  yych = *++p;
322  if (yych == 'i') goto yy46;
323  goto yy14;
324 yy37:
325  yych = *++p;
326  if (yych == 'f') goto yy47;
327  goto yy14;
328 yy38:
329  yych = *++p;
330  if (yych == 'c') goto yy48;
331  goto yy14;
332 yy39:
333  yych = *++p;
334  if (yych == 'o') goto yy49;
335  goto yy14;
336 yy40:
337  yych = *++p;
338  if (yych == 'l') goto yy50;
339  goto yy14;
340 yy41:
341  yych = *++p;
342  if (yych == 'b') goto yy51;
343  goto yy14;
344 yy42:
345  ++p;
346  { token = PIPEAT; break; }
347 yy44:
348  ++p;
349  { token = PIPE2; break; }
350 yy46:
351  yych = *++p;
352  if (yych == 'l') goto yy52;
353  goto yy14;
354 yy47:
355  yych = *++p;
356  if (yych == 'a') goto yy53;
357  goto yy14;
358 yy48:
359  yych = *++p;
360  if (yych == 'l') goto yy54;
361  goto yy14;
362 yy49:
363  yych = *++p;
364  if (yych == 'l') goto yy55;
365  goto yy14;
366 yy50:
367  yych = *++p;
368  if (yych == 'e') goto yy57;
369  goto yy14;
370 yy51:
371  yych = *++p;
372  if (yych == 'n') goto yy59;
373  goto yy14;
374 yy52:
375  yych = *++p;
376  if (yych == 'd') goto yy60;
377  goto yy14;
378 yy53:
379  yych = *++p;
380  if (yych == 'u') goto yy62;
381  goto yy14;
382 yy54:
383  yych = *++p;
384  if (yych == 'u') goto yy63;
385  goto yy14;
386 yy55:
387  yych = *++p;
388  if (yybm[0+yych] & 64) {
389  goto yy13;
390  }
391  { token = POOL; break; }
392 yy57:
393  yych = *++p;
394  if (yybm[0+yych] & 64) {
395  goto yy13;
396  }
397  { token = RULE; break; }
398 yy59:
399  yych = *++p;
400  if (yych == 'i') goto yy64;
401  goto yy14;
402 yy60:
403  yych = *++p;
404  if (yybm[0+yych] & 64) {
405  goto yy13;
406  }
407  { token = BUILD; break; }
408 yy62:
409  yych = *++p;
410  if (yych == 'l') goto yy65;
411  goto yy14;
412 yy63:
413  yych = *++p;
414  if (yych == 'd') goto yy66;
415  goto yy14;
416 yy64:
417  yych = *++p;
418  if (yych == 'n') goto yy67;
419  goto yy14;
420 yy65:
421  yych = *++p;
422  if (yych == 't') goto yy68;
423  goto yy14;
424 yy66:
425  yych = *++p;
426  if (yych == 'e') goto yy70;
427  goto yy14;
428 yy67:
429  yych = *++p;
430  if (yych == 'j') goto yy72;
431  goto yy14;
432 yy68:
433  yych = *++p;
434  if (yybm[0+yych] & 64) {
435  goto yy13;
436  }
437  { token = DEFAULT; break; }
438 yy70:
439  yych = *++p;
440  if (yybm[0+yych] & 64) {
441  goto yy13;
442  }
443  { token = INCLUDE; break; }
444 yy72:
445  yych = *++p;
446  if (yych != 'a') goto yy14;
447  yych = *++p;
448  if (yybm[0+yych] & 64) {
449  goto yy13;
450  }
451  { token = SUBNINJA; break; }
452 }
453 
454  }
455 
456  last_token_ = start;
457  ofs_ = p;
458  if (token != NEWLINE && token != TEOF)
459  EatWhitespace();
460  return token;
461 }
462 
463 bool Lexer::PeekToken(Token token) {
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 yy81;
516  }
517  if (yych <= 0x00) goto yy77;
518  if (yych == '$') goto yy84;
519  goto yy79;
520 yy77:
521  ++p;
522  { break; }
523 yy79:
524  ++p;
525 yy80:
526  { break; }
527 yy81:
528  yych = *++p;
529  if (yybm[0+yych] & 128) {
530  goto yy81;
531  }
532  { continue; }
533 yy84:
534  yych = *(q = ++p);
535  if (yych == '\n') goto yy85;
536  if (yych == '\r') goto yy87;
537  goto yy80;
538 yy85:
539  ++p;
540  { continue; }
541 yy87:
542  yych = *++p;
543  if (yych == '\n') goto yy89;
544  p = q;
545  goto yy80;
546 yy89:
547  ++p;
548  { continue; }
549 }
550 
551  }
552 }
553 
554 bool 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 yy95;
599  }
600  ++p;
601  {
602  last_token_ = start;
603  return false;
604  }
605 yy95:
606  yych = *++p;
607  if (yybm[0+yych] & 128) {
608  goto yy95;
609  }
610  {
611  out->assign(start, p - start);
612  break;
613  }
614 }
615 
616  }
617  last_token_ = start;
618  ofs_ = p;
619  EatWhitespace();
620  return true;
621 }
622 
623 bool 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 yy102;
669  }
670  if (yych <= '\r') {
671  if (yych <= 0x00) goto yy100;
672  if (yych <= '\n') goto yy105;
673  goto yy107;
674  } else {
675  if (yych <= ' ') goto yy105;
676  if (yych <= '$') goto yy109;
677  goto yy105;
678  }
679 yy100:
680  ++p;
681  {
682  last_token_ = start;
683  return Error("unexpected EOF", err);
684  }
685 yy102:
686  yych = *++p;
687  if (yybm[0+yych] & 16) {
688  goto yy102;
689  }
690  {
691  eval->AddText(StringPiece(start, p - start));
692  continue;
693  }
694 yy105:
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  }
707 yy107:
708  yych = *++p;
709  if (yych == '\n') goto yy110;
710  {
711  last_token_ = start;
712  return Error(DescribeLastError(), err);
713  }
714 yy109:
715  yych = *++p;
716  if (yybm[0+yych] & 64) {
717  goto yy122;
718  }
719  if (yych <= ' ') {
720  if (yych <= '\f') {
721  if (yych == '\n') goto yy114;
722  goto yy112;
723  } else {
724  if (yych <= '\r') goto yy117;
725  if (yych <= 0x1F) goto yy112;
726  goto yy118;
727  }
728  } else {
729  if (yych <= '/') {
730  if (yych == '$') goto yy120;
731  goto yy112;
732  } else {
733  if (yych <= ':') goto yy125;
734  if (yych <= '`') goto yy112;
735  if (yych <= '{') goto yy127;
736  goto yy112;
737  }
738  }
739 yy110:
740  ++p;
741  {
742  if (path)
743  p = start;
744  break;
745  }
746 yy112:
747  ++p;
748 yy113:
749  {
750  last_token_ = start;
751  return Error("bad $-escape (literal $ must be written as $$)", err);
752  }
753 yy114:
754  yych = *++p;
755  if (yybm[0+yych] & 32) {
756  goto yy114;
757  }
758  {
759  continue;
760  }
761 yy117:
762  yych = *++p;
763  if (yych == '\n') goto yy128;
764  goto yy113;
765 yy118:
766  ++p;
767  {
768  eval->AddText(StringPiece(" ", 1));
769  continue;
770  }
771 yy120:
772  ++p;
773  {
774  eval->AddText(StringPiece("$", 1));
775  continue;
776  }
777 yy122:
778  yych = *++p;
779  if (yybm[0+yych] & 64) {
780  goto yy122;
781  }
782  {
783  eval->AddSpecial(StringPiece(start + 1, p - start - 1));
784  continue;
785  }
786 yy125:
787  ++p;
788  {
789  eval->AddText(StringPiece(":", 1));
790  continue;
791  }
792 yy127:
793  yych = *(q = ++p);
794  if (yybm[0+yych] & 128) {
795  goto yy131;
796  }
797  goto yy113;
798 yy128:
799  yych = *++p;
800  if (yych == ' ') goto yy128;
801  {
802  continue;
803  }
804 yy131:
805  yych = *++p;
806  if (yybm[0+yych] & 128) {
807  goto yy131;
808  }
809  if (yych == '}') goto yy134;
810  p = q;
811  goto yy113;
812 yy134:
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)
824  EatWhitespace();
825  // Non-path strings end in newlines, so there's no whitespace to eat.
826  return true;
827 }
const char * str_
Definition: string_piece.h:66
void UnreadToken()
Rewind to the last read Token.
Definition: lexer.cc:116
StringPiece represents a slice of a string whose memory is managed externally.
Definition: string_piece.h:25
static const char * TokenErrorHint(Token expected)
Return a human-readable token hint, used in error messages.
Definition: lexer.cc:97
void EatWhitespace()
Skip past whitespace (called after each read token/ident/etc.).
Definition: lexer.cc:471
bool PeekToken(Token token)
If the next token is token, read it and return true.
Definition: lexer.cc:463
Token ReadToken()
Read a Token from the Token enum.
Definition: lexer.cc:120
void AddSpecial(StringPiece text)
Definition: eval_env.cc:120
bool Error(const std::string &message, std::string *err)
Construct an error message with context.
Definition: lexer.cc:25
std::string DescribeLastError()
If the last token read was an ERROR token, provide more info or the empty string. ...
Definition: lexer.cc:106
Token
Definition: lexer.h:32
void AddText(StringPiece text)
Definition: eval_env.cc:112
static const char * TokenName(Token t)
Return a human-readable form of a token, used in error messages.
Definition: lexer.cc:75
Lexer()
Definition: lexer.h:28
bool ReadIdent(std::string *out)
Read a simple identifier (a rule or variable name).
Definition: lexer.cc:554
void Error(const char *msg, va_list ap)
Definition: util.cc:96
bool ReadEvalString(EvalString *eval, bool path, std::string *err)
Read a $-escaped string.
Definition: lexer.cc:623
A tokenized string that contains variable references.
Definition: eval_env.h:34
void Start(StringPiece filename, StringPiece input)
Start parsing some input.
Definition: lexer.cc:68