Ninja
lexer.cc
Go to the documentation of this file.
1 /* Generated by re2c 0.13.5 */
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* context = input_.str_;
27  for (const char* p = input_.str_; p < last_token_; ++p) {
28  if (*p == '\n') {
29  ++line;
30  context = p + 1;
31  }
32  }
33  int col = last_token_ ? (int)(last_token_ - context) : 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 (context[len] == 0 || context[len] == '\n') {
47  truncated = false;
48  break;
49  }
50  }
51  *err += string(context, 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 '\r':
107  return "carriage returns are not allowed, use newlines";
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, 64, 64, 64, 64, 64, 64, 64,
132  64, 64, 0, 64, 64, 0, 64, 64,
133  64, 64, 64, 64, 64, 64, 64, 64,
134  64, 64, 64, 64, 64, 64, 64, 64,
135  192, 64, 64, 64, 64, 64, 64, 64,
136  64, 64, 64, 64, 64, 96, 96, 64,
137  96, 96, 96, 96, 96, 96, 96, 96,
138  96, 96, 64, 64, 64, 64, 64, 64,
139  64, 96, 96, 96, 96, 96, 96, 96,
140  96, 96, 96, 96, 96, 96, 96, 96,
141  96, 96, 96, 96, 96, 96, 96, 96,
142  96, 96, 96, 64, 64, 64, 64, 96,
143  64, 96, 96, 96, 96, 96, 96, 96,
144  96, 96, 96, 96, 96, 96, 96, 96,
145  96, 96, 96, 96, 96, 96, 96, 96,
146  96, 96, 96, 64, 64, 64, 64, 64,
147  64, 64, 64, 64, 64, 64, 64, 64,
148  64, 64, 64, 64, 64, 64, 64, 64,
149  64, 64, 64, 64, 64, 64, 64, 64,
150  64, 64, 64, 64, 64, 64, 64, 64,
151  64, 64, 64, 64, 64, 64, 64, 64,
152  64, 64, 64, 64, 64, 64, 64, 64,
153  64, 64, 64, 64, 64, 64, 64, 64,
154  64, 64, 64, 64, 64, 64, 64, 64,
155  64, 64, 64, 64, 64, 64, 64, 64,
156  64, 64, 64, 64, 64, 64, 64, 64,
157  64, 64, 64, 64, 64, 64, 64, 64,
158  64, 64, 64, 64, 64, 64, 64, 64,
159  64, 64, 64, 64, 64, 64, 64, 64,
160  64, 64, 64, 64, 64, 64, 64, 64,
161  64, 64, 64, 64, 64, 64, 64, 64,
162  64, 64, 64, 64, 64, 64, 64, 64,
163  };
164 
165  yych = *p;
166  if (yych <= '^') {
167  if (yych <= ',') {
168  if (yych <= 0x1F) {
169  if (yych <= 0x00) goto yy22;
170  if (yych == '\n') goto yy6;
171  goto yy24;
172  } else {
173  if (yych <= ' ') goto yy2;
174  if (yych == '#') goto yy4;
175  goto yy24;
176  }
177  } else {
178  if (yych <= ':') {
179  if (yych == '/') goto yy24;
180  if (yych <= '9') goto yy21;
181  goto yy15;
182  } else {
183  if (yych <= '=') {
184  if (yych <= '<') goto yy24;
185  goto yy13;
186  } else {
187  if (yych <= '@') goto yy24;
188  if (yych <= 'Z') goto yy21;
189  goto yy24;
190  }
191  }
192  }
193  } else {
194  if (yych <= 'i') {
195  if (yych <= 'b') {
196  if (yych == '`') goto yy24;
197  if (yych <= 'a') goto yy21;
198  goto yy8;
199  } else {
200  if (yych == 'd') goto yy12;
201  if (yych <= 'h') goto yy21;
202  goto yy19;
203  }
204  } else {
205  if (yych <= 'r') {
206  if (yych == 'p') goto yy10;
207  if (yych <= 'q') goto yy21;
208  goto yy11;
209  } else {
210  if (yych <= 'z') {
211  if (yych <= 's') goto yy20;
212  goto yy21;
213  } else {
214  if (yych == '|') goto yy17;
215  goto yy24;
216  }
217  }
218  }
219  }
220 yy2:
221  yyaccept = 0;
222  yych = *(q = ++p);
223  goto yy70;
224 yy3:
225  { token = INDENT; break; }
226 yy4:
227  yyaccept = 1;
228  yych = *(q = ++p);
229  if (yych <= 0x00) goto yy5;
230  if (yych != '\r') goto yy65;
231 yy5:
232  { token = ERROR; break; }
233 yy6:
234  ++p;
235 yy7:
236  { token = NEWLINE; break; }
237 yy8:
238  ++p;
239  if ((yych = *p) == 'u') goto yy59;
240  goto yy26;
241 yy9:
242  { token = IDENT; break; }
243 yy10:
244  yych = *++p;
245  if (yych == 'o') goto yy55;
246  goto yy26;
247 yy11:
248  yych = *++p;
249  if (yych == 'u') goto yy51;
250  goto yy26;
251 yy12:
252  yych = *++p;
253  if (yych == 'e') goto yy44;
254  goto yy26;
255 yy13:
256  ++p;
257  { token = EQUALS; break; }
258 yy15:
259  ++p;
260  { token = COLON; break; }
261 yy17:
262  ++p;
263  if ((yych = *p) == '|') goto yy42;
264  { token = PIPE; break; }
265 yy19:
266  yych = *++p;
267  if (yych == 'n') goto yy35;
268  goto yy26;
269 yy20:
270  yych = *++p;
271  if (yych == 'u') goto yy27;
272  goto yy26;
273 yy21:
274  yych = *++p;
275  goto yy26;
276 yy22:
277  ++p;
278  { token = TEOF; break; }
279 yy24:
280  yych = *++p;
281  goto yy5;
282 yy25:
283  ++p;
284  yych = *p;
285 yy26:
286  if (yybm[0+yych] & 32) {
287  goto yy25;
288  }
289  goto yy9;
290 yy27:
291  yych = *++p;
292  if (yych != 'b') goto yy26;
293  yych = *++p;
294  if (yych != 'n') goto yy26;
295  yych = *++p;
296  if (yych != 'i') goto yy26;
297  yych = *++p;
298  if (yych != 'n') goto yy26;
299  yych = *++p;
300  if (yych != 'j') goto yy26;
301  yych = *++p;
302  if (yych != 'a') goto yy26;
303  ++p;
304  if (yybm[0+(yych = *p)] & 32) {
305  goto yy25;
306  }
307  { token = SUBNINJA; break; }
308 yy35:
309  yych = *++p;
310  if (yych != 'c') goto yy26;
311  yych = *++p;
312  if (yych != 'l') goto yy26;
313  yych = *++p;
314  if (yych != 'u') goto yy26;
315  yych = *++p;
316  if (yych != 'd') goto yy26;
317  yych = *++p;
318  if (yych != 'e') goto yy26;
319  ++p;
320  if (yybm[0+(yych = *p)] & 32) {
321  goto yy25;
322  }
323  { token = INCLUDE; break; }
324 yy42:
325  ++p;
326  { token = PIPE2; break; }
327 yy44:
328  yych = *++p;
329  if (yych != 'f') goto yy26;
330  yych = *++p;
331  if (yych != 'a') goto yy26;
332  yych = *++p;
333  if (yych != 'u') goto yy26;
334  yych = *++p;
335  if (yych != 'l') goto yy26;
336  yych = *++p;
337  if (yych != 't') goto yy26;
338  ++p;
339  if (yybm[0+(yych = *p)] & 32) {
340  goto yy25;
341  }
342  { token = DEFAULT; break; }
343 yy51:
344  yych = *++p;
345  if (yych != 'l') goto yy26;
346  yych = *++p;
347  if (yych != 'e') goto yy26;
348  ++p;
349  if (yybm[0+(yych = *p)] & 32) {
350  goto yy25;
351  }
352  { token = RULE; break; }
353 yy55:
354  yych = *++p;
355  if (yych != 'o') goto yy26;
356  yych = *++p;
357  if (yych != 'l') goto yy26;
358  ++p;
359  if (yybm[0+(yych = *p)] & 32) {
360  goto yy25;
361  }
362  { token = POOL; break; }
363 yy59:
364  yych = *++p;
365  if (yych != 'i') goto yy26;
366  yych = *++p;
367  if (yych != 'l') goto yy26;
368  yych = *++p;
369  if (yych != 'd') goto yy26;
370  ++p;
371  if (yybm[0+(yych = *p)] & 32) {
372  goto yy25;
373  }
374  { token = BUILD; break; }
375 yy64:
376  ++p;
377  yych = *p;
378 yy65:
379  if (yybm[0+yych] & 64) {
380  goto yy64;
381  }
382  if (yych <= 0x00) goto yy66;
383  if (yych <= '\f') goto yy67;
384 yy66:
385  p = q;
386  if (yyaccept <= 0) {
387  goto yy3;
388  } else {
389  goto yy5;
390  }
391 yy67:
392  ++p;
393  { continue; }
394 yy69:
395  yyaccept = 0;
396  q = ++p;
397  yych = *p;
398 yy70:
399  if (yybm[0+yych] & 128) {
400  goto yy69;
401  }
402  if (yych == '\n') goto yy71;
403  if (yych == '#') goto yy64;
404  goto yy3;
405 yy71:
406  ++p;
407  yych = *p;
408  goto yy7;
409 }
410 
411  }
412 
413  last_token_ = start;
414  ofs_ = p;
415  if (token != NEWLINE && token != TEOF)
416  EatWhitespace();
417  return token;
418 }
419 
420 bool Lexer::PeekToken(Token token) {
421  Token t = ReadToken();
422  if (t == token)
423  return true;
424  UnreadToken();
425  return false;
426 }
427 
429  const char* p = ofs_;
430  for (;;) {
431  ofs_ = p;
432 
433 {
434  unsigned char yych;
435  static const unsigned char yybm[] = {
436  0, 0, 0, 0, 0, 0, 0, 0,
437  0, 0, 0, 0, 0, 0, 0, 0,
438  0, 0, 0, 0, 0, 0, 0, 0,
439  0, 0, 0, 0, 0, 0, 0, 0,
440  128, 0, 0, 0, 0, 0, 0, 0,
441  0, 0, 0, 0, 0, 0, 0, 0,
442  0, 0, 0, 0, 0, 0, 0, 0,
443  0, 0, 0, 0, 0, 0, 0, 0,
444  0, 0, 0, 0, 0, 0, 0, 0,
445  0, 0, 0, 0, 0, 0, 0, 0,
446  0, 0, 0, 0, 0, 0, 0, 0,
447  0, 0, 0, 0, 0, 0, 0, 0,
448  0, 0, 0, 0, 0, 0, 0, 0,
449  0, 0, 0, 0, 0, 0, 0, 0,
450  0, 0, 0, 0, 0, 0, 0, 0,
451  0, 0, 0, 0, 0, 0, 0, 0,
452  0, 0, 0, 0, 0, 0, 0, 0,
453  0, 0, 0, 0, 0, 0, 0, 0,
454  0, 0, 0, 0, 0, 0, 0, 0,
455  0, 0, 0, 0, 0, 0, 0, 0,
456  0, 0, 0, 0, 0, 0, 0, 0,
457  0, 0, 0, 0, 0, 0, 0, 0,
458  0, 0, 0, 0, 0, 0, 0, 0,
459  0, 0, 0, 0, 0, 0, 0, 0,
460  0, 0, 0, 0, 0, 0, 0, 0,
461  0, 0, 0, 0, 0, 0, 0, 0,
462  0, 0, 0, 0, 0, 0, 0, 0,
463  0, 0, 0, 0, 0, 0, 0, 0,
464  0, 0, 0, 0, 0, 0, 0, 0,
465  0, 0, 0, 0, 0, 0, 0, 0,
466  0, 0, 0, 0, 0, 0, 0, 0,
467  0, 0, 0, 0, 0, 0, 0, 0,
468  };
469  yych = *p;
470  if (yych <= ' ') {
471  if (yych <= 0x00) goto yy78;
472  if (yych <= 0x1F) goto yy80;
473  } else {
474  if (yych == '$') goto yy76;
475  goto yy80;
476  }
477  ++p;
478  yych = *p;
479  goto yy84;
480 yy75:
481  { continue; }
482 yy76:
483  ++p;
484  if ((yych = *p) == '\n') goto yy81;
485 yy77:
486  { break; }
487 yy78:
488  ++p;
489  { break; }
490 yy80:
491  yych = *++p;
492  goto yy77;
493 yy81:
494  ++p;
495  { continue; }
496 yy83:
497  ++p;
498  yych = *p;
499 yy84:
500  if (yybm[0+yych] & 128) {
501  goto yy83;
502  }
503  goto yy75;
504 }
505 
506  }
507 }
508 
509 bool Lexer::ReadIdent(string* out) {
510  const char* p = ofs_;
511  for (;;) {
512  const char* start = p;
513 
514 {
515  unsigned char yych;
516  static const unsigned char yybm[] = {
517  0, 0, 0, 0, 0, 0, 0, 0,
518  0, 0, 0, 0, 0, 0, 0, 0,
519  0, 0, 0, 0, 0, 0, 0, 0,
520  0, 0, 0, 0, 0, 0, 0, 0,
521  0, 0, 0, 0, 0, 0, 0, 0,
522  0, 0, 0, 0, 0, 128, 128, 0,
523  128, 128, 128, 128, 128, 128, 128, 128,
524  128, 128, 0, 0, 0, 0, 0, 0,
525  0, 128, 128, 128, 128, 128, 128, 128,
526  128, 128, 128, 128, 128, 128, 128, 128,
527  128, 128, 128, 128, 128, 128, 128, 128,
528  128, 128, 128, 0, 0, 0, 0, 128,
529  0, 128, 128, 128, 128, 128, 128, 128,
530  128, 128, 128, 128, 128, 128, 128, 128,
531  128, 128, 128, 128, 128, 128, 128, 128,
532  128, 128, 128, 0, 0, 0, 0, 0,
533  0, 0, 0, 0, 0, 0, 0, 0,
534  0, 0, 0, 0, 0, 0, 0, 0,
535  0, 0, 0, 0, 0, 0, 0, 0,
536  0, 0, 0, 0, 0, 0, 0, 0,
537  0, 0, 0, 0, 0, 0, 0, 0,
538  0, 0, 0, 0, 0, 0, 0, 0,
539  0, 0, 0, 0, 0, 0, 0, 0,
540  0, 0, 0, 0, 0, 0, 0, 0,
541  0, 0, 0, 0, 0, 0, 0, 0,
542  0, 0, 0, 0, 0, 0, 0, 0,
543  0, 0, 0, 0, 0, 0, 0, 0,
544  0, 0, 0, 0, 0, 0, 0, 0,
545  0, 0, 0, 0, 0, 0, 0, 0,
546  0, 0, 0, 0, 0, 0, 0, 0,
547  0, 0, 0, 0, 0, 0, 0, 0,
548  0, 0, 0, 0, 0, 0, 0, 0,
549  };
550  yych = *p;
551  if (yych <= '@') {
552  if (yych <= '.') {
553  if (yych <= ',') goto yy89;
554  } else {
555  if (yych <= '/') goto yy89;
556  if (yych >= ':') goto yy89;
557  }
558  } else {
559  if (yych <= '_') {
560  if (yych <= 'Z') goto yy87;
561  if (yych <= '^') goto yy89;
562  } else {
563  if (yych <= '`') goto yy89;
564  if (yych >= '{') goto yy89;
565  }
566  }
567 yy87:
568  ++p;
569  yych = *p;
570  goto yy92;
571 yy88:
572  {
573  out->assign(start, p - start);
574  break;
575  }
576 yy89:
577  ++p;
578  { return false; }
579 yy91:
580  ++p;
581  yych = *p;
582 yy92:
583  if (yybm[0+yych] & 128) {
584  goto yy91;
585  }
586  goto yy88;
587 }
588 
589  }
590  ofs_ = p;
591  EatWhitespace();
592  return true;
593 }
594 
595 bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) {
596  const char* p = ofs_;
597  const char* q;
598  const char* start;
599  for (;;) {
600  start = p;
601 
602 {
603  unsigned char yych;
604  static const unsigned char yybm[] = {
605  0, 128, 128, 128, 128, 128, 128, 128,
606  128, 128, 0, 128, 128, 0, 128, 128,
607  128, 128, 128, 128, 128, 128, 128, 128,
608  128, 128, 128, 128, 128, 128, 128, 128,
609  16, 128, 128, 128, 0, 128, 128, 128,
610  128, 128, 128, 128, 128, 224, 160, 128,
611  224, 224, 224, 224, 224, 224, 224, 224,
612  224, 224, 0, 128, 128, 128, 128, 128,
613  128, 224, 224, 224, 224, 224, 224, 224,
614  224, 224, 224, 224, 224, 224, 224, 224,
615  224, 224, 224, 224, 224, 224, 224, 224,
616  224, 224, 224, 128, 128, 128, 128, 224,
617  128, 224, 224, 224, 224, 224, 224, 224,
618  224, 224, 224, 224, 224, 224, 224, 224,
619  224, 224, 224, 224, 224, 224, 224, 224,
620  224, 224, 224, 128, 0, 128, 128, 128,
621  128, 128, 128, 128, 128, 128, 128, 128,
622  128, 128, 128, 128, 128, 128, 128, 128,
623  128, 128, 128, 128, 128, 128, 128, 128,
624  128, 128, 128, 128, 128, 128, 128, 128,
625  128, 128, 128, 128, 128, 128, 128, 128,
626  128, 128, 128, 128, 128, 128, 128, 128,
627  128, 128, 128, 128, 128, 128, 128, 128,
628  128, 128, 128, 128, 128, 128, 128, 128,
629  128, 128, 128, 128, 128, 128, 128, 128,
630  128, 128, 128, 128, 128, 128, 128, 128,
631  128, 128, 128, 128, 128, 128, 128, 128,
632  128, 128, 128, 128, 128, 128, 128, 128,
633  128, 128, 128, 128, 128, 128, 128, 128,
634  128, 128, 128, 128, 128, 128, 128, 128,
635  128, 128, 128, 128, 128, 128, 128, 128,
636  128, 128, 128, 128, 128, 128, 128, 128,
637  };
638  yych = *p;
639  if (yych <= ' ') {
640  if (yych <= '\n') {
641  if (yych <= 0x00) goto yy101;
642  if (yych >= '\n') goto yy97;
643  } else {
644  if (yych == '\r') goto yy103;
645  if (yych >= ' ') goto yy97;
646  }
647  } else {
648  if (yych <= '9') {
649  if (yych == '$') goto yy99;
650  } else {
651  if (yych <= ':') goto yy97;
652  if (yych == '|') goto yy97;
653  }
654  }
655  ++p;
656  yych = *p;
657  goto yy126;
658 yy96:
659  {
660  eval->AddText(StringPiece(start, p - start));
661  continue;
662  }
663 yy97:
664  ++p;
665  {
666  if (path) {
667  p = start;
668  break;
669  } else {
670  if (*start == '\n')
671  break;
672  eval->AddText(StringPiece(start, 1));
673  continue;
674  }
675  }
676 yy99:
677  ++p;
678  if ((yych = *p) <= '/') {
679  if (yych <= ' ') {
680  if (yych == '\n') goto yy115;
681  if (yych <= 0x1F) goto yy104;
682  goto yy106;
683  } else {
684  if (yych <= '$') {
685  if (yych <= '#') goto yy104;
686  goto yy108;
687  } else {
688  if (yych == '-') goto yy110;
689  goto yy104;
690  }
691  }
692  } else {
693  if (yych <= '^') {
694  if (yych <= ':') {
695  if (yych <= '9') goto yy110;
696  goto yy112;
697  } else {
698  if (yych <= '@') goto yy104;
699  if (yych <= 'Z') goto yy110;
700  goto yy104;
701  }
702  } else {
703  if (yych <= '`') {
704  if (yych <= '_') goto yy110;
705  goto yy104;
706  } else {
707  if (yych <= 'z') goto yy110;
708  if (yych <= '{') goto yy114;
709  goto yy104;
710  }
711  }
712  }
713 yy100:
714  {
715  last_token_ = start;
716  return Error(DescribeLastError(), err);
717  }
718 yy101:
719  ++p;
720  {
721  last_token_ = start;
722  return Error("unexpected EOF", err);
723  }
724 yy103:
725  yych = *++p;
726  goto yy100;
727 yy104:
728  ++p;
729 yy105:
730  {
731  last_token_ = start;
732  return Error("bad $-escape (literal $ must be written as $$)", err);
733  }
734 yy106:
735  ++p;
736  {
737  eval->AddText(StringPiece(" ", 1));
738  continue;
739  }
740 yy108:
741  ++p;
742  {
743  eval->AddText(StringPiece("$", 1));
744  continue;
745  }
746 yy110:
747  ++p;
748  yych = *p;
749  goto yy124;
750 yy111:
751  {
752  eval->AddSpecial(StringPiece(start + 1, p - start - 1));
753  continue;
754  }
755 yy112:
756  ++p;
757  {
758  eval->AddText(StringPiece(":", 1));
759  continue;
760  }
761 yy114:
762  yych = *(q = ++p);
763  if (yybm[0+yych] & 32) {
764  goto yy118;
765  }
766  goto yy105;
767 yy115:
768  ++p;
769  yych = *p;
770  if (yybm[0+yych] & 16) {
771  goto yy115;
772  }
773  {
774  continue;
775  }
776 yy118:
777  ++p;
778  yych = *p;
779  if (yybm[0+yych] & 32) {
780  goto yy118;
781  }
782  if (yych == '}') goto yy121;
783  p = q;
784  goto yy105;
785 yy121:
786  ++p;
787  {
788  eval->AddSpecial(StringPiece(start + 2, p - start - 3));
789  continue;
790  }
791 yy123:
792  ++p;
793  yych = *p;
794 yy124:
795  if (yybm[0+yych] & 64) {
796  goto yy123;
797  }
798  goto yy111;
799 yy125:
800  ++p;
801  yych = *p;
802 yy126:
803  if (yybm[0+yych] & 128) {
804  goto yy125;
805  }
806  goto yy96;
807 }
808 
809  }
810  last_token_ = start;
811  ofs_ = p;
812  if (path)
813  EatWhitespace();
814  // Non-path strings end in newlines, so there's no whitespace to eat.
815  return true;
816 }
const char * last_token_
Definition: lexer.h:102
const char * str_
Definition: string_piece.h:49
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: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:428
string AsString() const
Convert the slice into a full-fledged std::string, copying the data into a new string.
Definition: string_piece.h:45
bool PeekToken(Token token)
If the next token is token, read it and return true.
Definition: lexer.cc:420
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:119
void AddSpecial(StringPiece text)
Definition: eval_env.cc:65
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:509
bool ReadEvalString(EvalString *eval, bool path, string *err)
Read a $-escaped string.
Definition: lexer.cc:595
void AddText(StringPiece text)
Definition: eval_env.cc:57
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:59
const char * ofs_
Definition: lexer.h:101
void Start(StringPiece filename, StringPiece input)
Start parsing some input.
Definition: lexer.cc:66