Ninja
lexer.cc
Go to the documentation of this file.
1 /* Generated by re2c 1.1.1 */
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 POOL: return "'pool'";
89  case RULE: return "'rule'";
90  case SUBNINJA: return "'subninja'";
91  case TEOF: return "eof";
92  }
93  return NULL; // not reached
94 }
95 
96 const char* Lexer::TokenErrorHint(Token expected) {
97  switch (expected) {
98  case COLON:
99  return " ($ also escapes ':')";
100  default:
101  return "";
102  }
103 }
104 
106  if (last_token_) {
107  switch (last_token_[0]) {
108  case '\t':
109  return "tabs are not allowed, use spaces";
110  }
111  }
112  return "lexing error";
113 }
114 
116  ofs_ = last_token_;
117 }
118 
120  const char* p = ofs_;
121  const char* q;
122  const char* start;
123  Lexer::Token token;
124  for (;;) {
125  start = p;
126 
127 {
128  unsigned char yych;
129  unsigned int yyaccept = 0;
130  static const unsigned char yybm[] = {
131  0, 128, 128, 128, 128, 128, 128, 128,
132  128, 128, 0, 128, 128, 128, 128, 128,
133  128, 128, 128, 128, 128, 128, 128, 128,
134  128, 128, 128, 128, 128, 128, 128, 128,
135  160, 128, 128, 128, 128, 128, 128, 128,
136  128, 128, 128, 128, 128, 192, 192, 128,
137  192, 192, 192, 192, 192, 192, 192, 192,
138  192, 192, 128, 128, 128, 128, 128, 128,
139  128, 192, 192, 192, 192, 192, 192, 192,
140  192, 192, 192, 192, 192, 192, 192, 192,
141  192, 192, 192, 192, 192, 192, 192, 192,
142  192, 192, 192, 128, 128, 128, 128, 192,
143  128, 192, 192, 192, 192, 192, 192, 192,
144  192, 192, 192, 192, 192, 192, 192, 192,
145  192, 192, 192, 192, 192, 192, 192, 192,
146  192, 192, 192, 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  128, 128, 128, 128, 128, 128, 128, 128,
162  128, 128, 128, 128, 128, 128, 128, 128,
163  };
164  yych = *p;
165  if (yybm[0+yych] & 32) {
166  goto yy9;
167  }
168  if (yych <= '^') {
169  if (yych <= ',') {
170  if (yych <= '\f') {
171  if (yych <= 0x00) goto yy2;
172  if (yych == '\n') goto yy6;
173  goto yy4;
174  } else {
175  if (yych <= '\r') goto yy8;
176  if (yych == '#') goto yy12;
177  goto yy4;
178  }
179  } else {
180  if (yych <= ':') {
181  if (yych == '/') goto yy4;
182  if (yych <= '9') goto yy13;
183  goto yy16;
184  } else {
185  if (yych <= '=') {
186  if (yych <= '<') goto yy4;
187  goto yy18;
188  } else {
189  if (yych <= '@') goto yy4;
190  if (yych <= 'Z') goto yy13;
191  goto yy4;
192  }
193  }
194  }
195  } else {
196  if (yych <= 'i') {
197  if (yych <= 'b') {
198  if (yych == '`') goto yy4;
199  if (yych <= 'a') goto yy13;
200  goto yy20;
201  } else {
202  if (yych == 'd') goto yy21;
203  if (yych <= 'h') goto yy13;
204  goto yy22;
205  }
206  } else {
207  if (yych <= 'r') {
208  if (yych == 'p') goto yy23;
209  if (yych <= 'q') goto yy13;
210  goto yy24;
211  } else {
212  if (yych <= 'z') {
213  if (yych <= 's') goto yy25;
214  goto yy13;
215  } else {
216  if (yych == '|') goto yy26;
217  goto yy4;
218  }
219  }
220  }
221  }
222 yy2:
223  ++p;
224  { token = TEOF; break; }
225 yy4:
226  ++p;
227 yy5:
228  { token = ERROR; break; }
229 yy6:
230  ++p;
231  { token = NEWLINE; break; }
232 yy8:
233  yych = *++p;
234  if (yych == '\n') goto yy28;
235  goto yy5;
236 yy9:
237  yyaccept = 0;
238  yych = *(q = ++p);
239  if (yybm[0+yych] & 32) {
240  goto yy9;
241  }
242  if (yych <= '\f') {
243  if (yych == '\n') goto yy6;
244  } else {
245  if (yych <= '\r') goto yy30;
246  if (yych == '#') goto yy32;
247  }
248 yy11:
249  { token = INDENT; break; }
250 yy12:
251  yyaccept = 1;
252  yych = *(q = ++p);
253  if (yych <= 0x00) goto yy5;
254  goto yy33;
255 yy13:
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  yych = *++p;
294  if (yych == '|') 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  yych = *++p;
311 yy33:
312  if (yybm[0+yych] & 128) {
313  goto yy32;
314  }
315  if (yych <= 0x00) goto yy31;
316  ++p;
317  { continue; }
318 yy36:
319  yych = *++p;
320  if (yych == 'i') goto yy44;
321  goto yy14;
322 yy37:
323  yych = *++p;
324  if (yych == 'f') goto yy45;
325  goto yy14;
326 yy38:
327  yych = *++p;
328  if (yych == 'c') goto yy46;
329  goto yy14;
330 yy39:
331  yych = *++p;
332  if (yych == 'o') goto yy47;
333  goto yy14;
334 yy40:
335  yych = *++p;
336  if (yych == 'l') goto yy48;
337  goto yy14;
338 yy41:
339  yych = *++p;
340  if (yych == 'b') goto yy49;
341  goto yy14;
342 yy42:
343  ++p;
344  { token = PIPE2; break; }
345 yy44:
346  yych = *++p;
347  if (yych == 'l') goto yy50;
348  goto yy14;
349 yy45:
350  yych = *++p;
351  if (yych == 'a') goto yy51;
352  goto yy14;
353 yy46:
354  yych = *++p;
355  if (yych == 'l') goto yy52;
356  goto yy14;
357 yy47:
358  yych = *++p;
359  if (yych == 'l') goto yy53;
360  goto yy14;
361 yy48:
362  yych = *++p;
363  if (yych == 'e') goto yy55;
364  goto yy14;
365 yy49:
366  yych = *++p;
367  if (yych == 'n') goto yy57;
368  goto yy14;
369 yy50:
370  yych = *++p;
371  if (yych == 'd') goto yy58;
372  goto yy14;
373 yy51:
374  yych = *++p;
375  if (yych == 'u') goto yy60;
376  goto yy14;
377 yy52:
378  yych = *++p;
379  if (yych == 'u') goto yy61;
380  goto yy14;
381 yy53:
382  yych = *++p;
383  if (yybm[0+yych] & 64) {
384  goto yy13;
385  }
386  { token = POOL; break; }
387 yy55:
388  yych = *++p;
389  if (yybm[0+yych] & 64) {
390  goto yy13;
391  }
392  { token = RULE; break; }
393 yy57:
394  yych = *++p;
395  if (yych == 'i') goto yy62;
396  goto yy14;
397 yy58:
398  yych = *++p;
399  if (yybm[0+yych] & 64) {
400  goto yy13;
401  }
402  { token = BUILD; break; }
403 yy60:
404  yych = *++p;
405  if (yych == 'l') goto yy63;
406  goto yy14;
407 yy61:
408  yych = *++p;
409  if (yych == 'd') goto yy64;
410  goto yy14;
411 yy62:
412  yych = *++p;
413  if (yych == 'n') goto yy65;
414  goto yy14;
415 yy63:
416  yych = *++p;
417  if (yych == 't') goto yy66;
418  goto yy14;
419 yy64:
420  yych = *++p;
421  if (yych == 'e') goto yy68;
422  goto yy14;
423 yy65:
424  yych = *++p;
425  if (yych == 'j') goto yy70;
426  goto yy14;
427 yy66:
428  yych = *++p;
429  if (yybm[0+yych] & 64) {
430  goto yy13;
431  }
432  { token = DEFAULT; break; }
433 yy68:
434  yych = *++p;
435  if (yybm[0+yych] & 64) {
436  goto yy13;
437  }
438  { token = INCLUDE; break; }
439 yy70:
440  yych = *++p;
441  if (yych != 'a') goto yy14;
442  yych = *++p;
443  if (yybm[0+yych] & 64) {
444  goto yy13;
445  }
446  { token = SUBNINJA; break; }
447 }
448 
449  }
450 
451  last_token_ = start;
452  ofs_ = p;
453  if (token != NEWLINE && token != TEOF)
454  EatWhitespace();
455  return token;
456 }
457 
458 bool Lexer::PeekToken(Token token) {
459  Token t = ReadToken();
460  if (t == token)
461  return true;
462  UnreadToken();
463  return false;
464 }
465 
467  const char* p = ofs_;
468  const char* q;
469  for (;;) {
470  ofs_ = p;
471 
472 {
473  unsigned char yych;
474  static const unsigned char yybm[] = {
475  0, 0, 0, 0, 0, 0, 0, 0,
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  128, 0, 0, 0, 0, 0, 0, 0,
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  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  };
508  yych = *p;
509  if (yybm[0+yych] & 128) {
510  goto yy79;
511  }
512  if (yych <= 0x00) goto yy75;
513  if (yych == '$') goto yy82;
514  goto yy77;
515 yy75:
516  ++p;
517  { break; }
518 yy77:
519  ++p;
520 yy78:
521  { break; }
522 yy79:
523  yych = *++p;
524  if (yybm[0+yych] & 128) {
525  goto yy79;
526  }
527  { continue; }
528 yy82:
529  yych = *(q = ++p);
530  if (yych == '\n') goto yy83;
531  if (yych == '\r') goto yy85;
532  goto yy78;
533 yy83:
534  ++p;
535  { continue; }
536 yy85:
537  yych = *++p;
538  if (yych == '\n') goto yy87;
539  p = q;
540  goto yy78;
541 yy87:
542  ++p;
543  { continue; }
544 }
545 
546  }
547 }
548 
549 bool Lexer::ReadIdent(string* out) {
550  const char* p = ofs_;
551  const char* start;
552  for (;;) {
553  start = p;
554 
555 {
556  unsigned char yych;
557  static const unsigned char yybm[] = {
558  0, 0, 0, 0, 0, 0, 0, 0,
559  0, 0, 0, 0, 0, 0, 0, 0,
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, 128, 128, 0,
564  128, 128, 128, 128, 128, 128, 128, 128,
565  128, 128, 0, 0, 0, 0, 0, 0,
566  0, 128, 128, 128, 128, 128, 128, 128,
567  128, 128, 128, 128, 128, 128, 128, 128,
568  128, 128, 128, 128, 128, 128, 128, 128,
569  128, 128, 128, 0, 0, 0, 0, 128,
570  0, 128, 128, 128, 128, 128, 128, 128,
571  128, 128, 128, 128, 128, 128, 128, 128,
572  128, 128, 128, 128, 128, 128, 128, 128,
573  128, 128, 128, 0, 0, 0, 0, 0,
574  0, 0, 0, 0, 0, 0, 0, 0,
575  0, 0, 0, 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  };
591  yych = *p;
592  if (yybm[0+yych] & 128) {
593  goto yy93;
594  }
595  ++p;
596  {
597  last_token_ = start;
598  return false;
599  }
600 yy93:
601  yych = *++p;
602  if (yybm[0+yych] & 128) {
603  goto yy93;
604  }
605  {
606  out->assign(start, p - start);
607  break;
608  }
609 }
610 
611  }
612  last_token_ = start;
613  ofs_ = p;
614  EatWhitespace();
615  return true;
616 }
617 
618 bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) {
619  const char* p = ofs_;
620  const char* q;
621  const char* start;
622  for (;;) {
623  start = p;
624 
625 {
626  unsigned char yych;
627  static const unsigned char yybm[] = {
628  0, 16, 16, 16, 16, 16, 16, 16,
629  16, 16, 0, 16, 16, 0, 16, 16,
630  16, 16, 16, 16, 16, 16, 16, 16,
631  16, 16, 16, 16, 16, 16, 16, 16,
632  32, 16, 16, 16, 0, 16, 16, 16,
633  16, 16, 16, 16, 16, 208, 144, 16,
634  208, 208, 208, 208, 208, 208, 208, 208,
635  208, 208, 0, 16, 16, 16, 16, 16,
636  16, 208, 208, 208, 208, 208, 208, 208,
637  208, 208, 208, 208, 208, 208, 208, 208,
638  208, 208, 208, 208, 208, 208, 208, 208,
639  208, 208, 208, 16, 16, 16, 16, 208,
640  16, 208, 208, 208, 208, 208, 208, 208,
641  208, 208, 208, 208, 208, 208, 208, 208,
642  208, 208, 208, 208, 208, 208, 208, 208,
643  208, 208, 208, 16, 0, 16, 16, 16,
644  16, 16, 16, 16, 16, 16, 16, 16,
645  16, 16, 16, 16, 16, 16, 16, 16,
646  16, 16, 16, 16, 16, 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  };
661  yych = *p;
662  if (yybm[0+yych] & 16) {
663  goto yy100;
664  }
665  if (yych <= '\r') {
666  if (yych <= 0x00) goto yy98;
667  if (yych <= '\n') goto yy103;
668  goto yy105;
669  } else {
670  if (yych <= ' ') goto yy103;
671  if (yych <= '$') goto yy107;
672  goto yy103;
673  }
674 yy98:
675  ++p;
676  {
677  last_token_ = start;
678  return Error("unexpected EOF", err);
679  }
680 yy100:
681  yych = *++p;
682  if (yybm[0+yych] & 16) {
683  goto yy100;
684  }
685  {
686  eval->AddText(StringPiece(start, p - start));
687  continue;
688  }
689 yy103:
690  ++p;
691  {
692  if (path) {
693  p = start;
694  break;
695  } else {
696  if (*start == '\n')
697  break;
698  eval->AddText(StringPiece(start, 1));
699  continue;
700  }
701  }
702 yy105:
703  yych = *++p;
704  if (yych == '\n') goto yy108;
705  {
706  last_token_ = start;
707  return Error(DescribeLastError(), err);
708  }
709 yy107:
710  yych = *++p;
711  if (yybm[0+yych] & 64) {
712  goto yy120;
713  }
714  if (yych <= ' ') {
715  if (yych <= '\f') {
716  if (yych == '\n') goto yy112;
717  goto yy110;
718  } else {
719  if (yych <= '\r') goto yy115;
720  if (yych <= 0x1F) goto yy110;
721  goto yy116;
722  }
723  } else {
724  if (yych <= '/') {
725  if (yych == '$') goto yy118;
726  goto yy110;
727  } else {
728  if (yych <= ':') goto yy123;
729  if (yych <= '`') goto yy110;
730  if (yych <= '{') goto yy125;
731  goto yy110;
732  }
733  }
734 yy108:
735  ++p;
736  {
737  if (path)
738  p = start;
739  break;
740  }
741 yy110:
742  ++p;
743 yy111:
744  {
745  last_token_ = start;
746  return Error("bad $-escape (literal $ must be written as $$)", err);
747  }
748 yy112:
749  yych = *++p;
750  if (yybm[0+yych] & 32) {
751  goto yy112;
752  }
753  {
754  continue;
755  }
756 yy115:
757  yych = *++p;
758  if (yych == '\n') goto yy126;
759  goto yy111;
760 yy116:
761  ++p;
762  {
763  eval->AddText(StringPiece(" ", 1));
764  continue;
765  }
766 yy118:
767  ++p;
768  {
769  eval->AddText(StringPiece("$", 1));
770  continue;
771  }
772 yy120:
773  yych = *++p;
774  if (yybm[0+yych] & 64) {
775  goto yy120;
776  }
777  {
778  eval->AddSpecial(StringPiece(start + 1, p - start - 1));
779  continue;
780  }
781 yy123:
782  ++p;
783  {
784  eval->AddText(StringPiece(":", 1));
785  continue;
786  }
787 yy125:
788  yych = *(q = ++p);
789  if (yybm[0+yych] & 128) {
790  goto yy129;
791  }
792  goto yy111;
793 yy126:
794  yych = *++p;
795  if (yych == ' ') goto yy126;
796  {
797  continue;
798  }
799 yy129:
800  yych = *++p;
801  if (yybm[0+yych] & 128) {
802  goto yy129;
803  }
804  if (yych == '}') goto yy132;
805  p = q;
806  goto yy111;
807 yy132:
808  ++p;
809  {
810  eval->AddSpecial(StringPiece(start + 2, p - start - 3));
811  continue;
812  }
813 }
814 
815  }
816  last_token_ = start;
817  ofs_ = p;
818  if (path)
819  EatWhitespace();
820  // Non-path strings end in newlines, so there's no whitespace to eat.
821  return true;
822 }
const char * str_
Definition: string_piece.h:66
void UnreadToken()
Rewind to the last read Token.
Definition: lexer.cc:115
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:96
void EatWhitespace()
Skip past whitespace (called after each read token/ident/etc.).
Definition: lexer.cc:466
bool PeekToken(Token token)
If the next token is token, read it and return true.
Definition: lexer.cc:458
Token ReadToken()
Read a Token from the Token enum.
Definition: lexer.cc:119
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:105
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:549
bool ReadEvalString(EvalString *eval, bool path, std::string *err)
Read a $-escaped string.
Definition: lexer.cc:618
A tokenized string that contains variable references.
Definition: eval_env.h:34
void Error(const char *msg,...)
Log an error message.
Definition: util.cc:86
void Start(StringPiece filename, StringPiece input)
Start parsing some input.
Definition: lexer.cc:68