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 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  }
223 yy1:
224  ++p;
225  { token = TEOF; break; }
226 yy2:
227  ++p;
228 yy3:
229  { token = ERROR; break; }
230 yy4:
231  ++p;
232  { token = NEWLINE; break; }
233 yy5:
234  yych = *++p;
235  if (yych == '\n') goto yy20;
236  goto yy3;
237 yy6:
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  }
249 yy7:
250  { token = INDENT; break; }
251 yy8:
252  yyaccept = 1;
253  yych = *(q = ++p);
254  if (yych <= 0x00) goto yy3;
255  goto yy24;
256 yy9:
257  yych = *++p;
258 yy10:
259  if (yybm[0+yych] & 64) {
260  goto yy9;
261  }
262  { token = IDENT; break; }
263 yy11:
264  ++p;
265  { token = COLON; break; }
266 yy12:
267  ++p;
268  { token = EQUALS; break; }
269 yy13:
270  yych = *++p;
271  if (yych == 'u') goto yy25;
272  goto yy10;
273 yy14:
274  yych = *++p;
275  if (yych == 'e') goto yy26;
276  goto yy10;
277 yy15:
278  yych = *++p;
279  if (yych == 'n') goto yy27;
280  goto yy10;
281 yy16:
282  yych = *++p;
283  if (yych == 'o') goto yy28;
284  goto yy10;
285 yy17:
286  yych = *++p;
287  if (yych == 'u') goto yy29;
288  goto yy10;
289 yy18:
290  yych = *++p;
291  if (yych == 'u') goto yy30;
292  goto yy10;
293 yy19:
294  yych = *++p;
295  if (yych == '@') goto yy31;
296  if (yych == '|') goto yy32;
297  { token = PIPE; break; }
298 yy20:
299  ++p;
300  { token = NEWLINE; break; }
301 yy21:
302  yych = *++p;
303  if (yych == '\n') goto yy20;
304 yy22:
305  p = q;
306  if (yyaccept == 0) {
307  goto yy7;
308  } else {
309  goto yy3;
310  }
311 yy23:
312  yych = *++p;
313 yy24:
314  if (yybm[0+yych] & 128) {
315  goto yy23;
316  }
317  if (yych <= 0x00) goto yy22;
318  ++p;
319  { continue; }
320 yy25:
321  yych = *++p;
322  if (yych == 'i') goto yy33;
323  goto yy10;
324 yy26:
325  yych = *++p;
326  if (yych == 'f') goto yy34;
327  goto yy10;
328 yy27:
329  yych = *++p;
330  if (yych == 'c') goto yy35;
331  goto yy10;
332 yy28:
333  yych = *++p;
334  if (yych == 'o') goto yy36;
335  goto yy10;
336 yy29:
337  yych = *++p;
338  if (yych == 'l') goto yy37;
339  goto yy10;
340 yy30:
341  yych = *++p;
342  if (yych == 'b') goto yy38;
343  goto yy10;
344 yy31:
345  ++p;
346  { token = PIPEAT; break; }
347 yy32:
348  ++p;
349  { token = PIPE2; break; }
350 yy33:
351  yych = *++p;
352  if (yych == 'l') goto yy39;
353  goto yy10;
354 yy34:
355  yych = *++p;
356  if (yych == 'a') goto yy40;
357  goto yy10;
358 yy35:
359  yych = *++p;
360  if (yych == 'l') goto yy41;
361  goto yy10;
362 yy36:
363  yych = *++p;
364  if (yych == 'l') goto yy42;
365  goto yy10;
366 yy37:
367  yych = *++p;
368  if (yych == 'e') goto yy43;
369  goto yy10;
370 yy38:
371  yych = *++p;
372  if (yych == 'n') goto yy44;
373  goto yy10;
374 yy39:
375  yych = *++p;
376  if (yych == 'd') goto yy45;
377  goto yy10;
378 yy40:
379  yych = *++p;
380  if (yych == 'u') goto yy46;
381  goto yy10;
382 yy41:
383  yych = *++p;
384  if (yych == 'u') goto yy47;
385  goto yy10;
386 yy42:
387  yych = *++p;
388  if (yybm[0+yych] & 64) {
389  goto yy9;
390  }
391  { token = POOL; break; }
392 yy43:
393  yych = *++p;
394  if (yybm[0+yych] & 64) {
395  goto yy9;
396  }
397  { token = RULE; break; }
398 yy44:
399  yych = *++p;
400  if (yych == 'i') goto yy48;
401  goto yy10;
402 yy45:
403  yych = *++p;
404  if (yybm[0+yych] & 64) {
405  goto yy9;
406  }
407  { token = BUILD; break; }
408 yy46:
409  yych = *++p;
410  if (yych == 'l') goto yy49;
411  goto yy10;
412 yy47:
413  yych = *++p;
414  if (yych == 'd') goto yy50;
415  goto yy10;
416 yy48:
417  yych = *++p;
418  if (yych == 'n') goto yy51;
419  goto yy10;
420 yy49:
421  yych = *++p;
422  if (yych == 't') goto yy52;
423  goto yy10;
424 yy50:
425  yych = *++p;
426  if (yych == 'e') goto yy53;
427  goto yy10;
428 yy51:
429  yych = *++p;
430  if (yych == 'j') goto yy54;
431  goto yy10;
432 yy52:
433  yych = *++p;
434  if (yybm[0+yych] & 64) {
435  goto yy9;
436  }
437  { token = DEFAULT; break; }
438 yy53:
439  yych = *++p;
440  if (yybm[0+yych] & 64) {
441  goto yy9;
442  }
443  { token = INCLUDE; break; }
444 yy54:
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)
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 yy59;
516  }
517  if (yych <= 0x00) goto yy56;
518  if (yych == '$') goto yy60;
519  goto yy57;
520 yy56:
521  ++p;
522  { break; }
523 yy57:
524  ++p;
525 yy58:
526  { break; }
527 yy59:
528  yych = *++p;
529  if (yybm[0+yych] & 128) {
530  goto yy59;
531  }
532  { continue; }
533 yy60:
534  yych = *(q = ++p);
535  if (yych == '\n') goto yy61;
536  if (yych == '\r') goto yy62;
537  goto yy58;
538 yy61:
539  ++p;
540  { continue; }
541 yy62:
542  yych = *++p;
543  if (yych == '\n') goto yy63;
544  p = q;
545  goto yy58;
546 yy63:
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 yy65;
599  }
600  ++p;
601  {
602  last_token_ = start;
603  return false;
604  }
605 yy65:
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;
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 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  }
679 yy67:
680  ++p;
681  {
682  last_token_ = start;
683  return Error("unexpected EOF", err);
684  }
685 yy68:
686  yych = *++p;
687  if (yybm[0+yych] & 16) {
688  goto yy68;
689  }
690  {
691  eval->AddText(StringPiece(start, p - start));
692  continue;
693  }
694 yy69:
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 yy70:
708  yych = *++p;
709  if (yych == '\n') goto yy72;
710  {
711  last_token_ = start;
712  return Error(DescribeLastError(), err);
713  }
714 yy71:
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  }
739 yy72:
740  ++p;
741  {
742  if (path)
743  p = start;
744  break;
745  }
746 yy73:
747  ++p;
748 yy74:
749  {
750  last_token_ = start;
751  return Error("bad $-escape (literal $ must be written as $$)", err);
752  }
753 yy75:
754  yych = *++p;
755  if (yybm[0+yych] & 32) {
756  goto yy75;
757  }
758  {
759  continue;
760  }
761 yy76:
762  yych = *++p;
763  if (yych == '\n') goto yy82;
764  goto yy74;
765 yy77:
766  ++p;
767  {
768  eval->AddText(StringPiece(" ", 1));
769  continue;
770  }
771 yy78:
772  ++p;
773  {
774  eval->AddText(StringPiece("$", 1));
775  continue;
776  }
777 yy79:
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  }
786 yy80:
787  ++p;
788  {
789  eval->AddText(StringPiece(":", 1));
790  continue;
791  }
792 yy81:
793  yych = *(q = ++p);
794  if (yybm[0+yych] & 128) {
795  goto yy83;
796  }
797  goto yy74;
798 yy82:
799  yych = *++p;
800  if (yych == ' ') goto yy82;
801  {
802  continue;
803  }
804 yy83:
805  yych = *++p;
806  if (yybm[0+yych] & 128) {
807  goto yy83;
808  }
809  if (yych == '}') goto yy84;
810  p = q;
811  goto yy74;
812 yy84:
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 }
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
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
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
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
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
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.
Definition: string_piece.h:25
const char * str_
Definition: string_piece.h:70
void Error(const char *msg, va_list ap)
Definition: util.cc:98