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