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