disallow crlf in manifest files
[platform/upstream/ninja.git] / src / lexer.cc
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_ ? 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 RULE:     return "'rule'";
87   case SUBNINJA: return "'subninja'";
88   case TEOF:     return "eof";
89   }
90   return NULL;  // not reached
91 }
92
93 const char* Lexer::TokenErrorHint(Token t) {
94   switch (t) {
95   case ERROR:    return "";
96   case BUILD:    return "";
97   case COLON:    return " ($ also escapes ':')";
98   case DEFAULT:  return "";
99   case EQUALS:   return "";
100   case IDENT:    return "";
101   case INCLUDE:  return "";
102   case INDENT:   return "";
103   case NEWLINE:  return "";
104   case PIPE2:    return "";
105   case PIPE:     return "";
106   case RULE:     return "";
107   case SUBNINJA: return "";
108   case TEOF:     return "";
109   }
110   return "";
111 }
112
113 void Lexer::UnreadToken() {
114   ofs_ = last_token_;
115 }
116
117 Lexer::Token Lexer::ReadToken() {
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,  64,  64,  64,  64,  64,  64,  64, 
130                  64,  64,   0,  64,  64,   0,  64,  64, 
131                  64,  64,  64,  64,  64,  64,  64,  64, 
132                  64,  64,  64,  64,  64,  64,  64,  64, 
133                 192,  64,  64,  64,  64,  64,  64,  64, 
134                  64,  64,  64,  64,  64,  96,  96,  64, 
135                  96,  96,  96,  96,  96,  96,  96,  96, 
136                  96,  96,  64,  64,  64,  64,  64,  64, 
137                  64,  96,  96,  96,  96,  96,  96,  96, 
138                  96,  96,  96,  96,  96,  96,  96,  96, 
139                  96,  96,  96,  96,  96,  96,  96,  96, 
140                  96,  96,  96,  64,  64,  64,  64,  96, 
141                  64,  96,  96,  96,  96,  96,  96,  96, 
142                  96,  96,  96,  96,  96,  96,  96,  96, 
143                  96,  96,  96,  96,  96,  96,  96,  96, 
144                  96,  96,  96,  64,  64,  64,  64,  64, 
145                  64,  64,  64,  64,  64,  64,  64,  64, 
146                  64,  64,  64,  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         };
162
163         yych = *p;
164         if (yych <= 'Z') {
165                 if (yych <= ',') {
166                         if (yych <= 0x1F) {
167                                 if (yych <= 0x00) goto yy21;
168                                 if (yych == '\n') goto yy6;
169                                 goto yy23;
170                         } else {
171                                 if (yych <= ' ') goto yy2;
172                                 if (yych == '#') goto yy4;
173                                 goto yy23;
174                         }
175                 } else {
176                         if (yych <= ':') {
177                                 if (yych == '/') goto yy23;
178                                 if (yych <= '9') goto yy20;
179                                 goto yy14;
180                         } else {
181                                 if (yych == '=') goto yy12;
182                                 if (yych <= '@') goto yy23;
183                                 goto yy20;
184                         }
185                 }
186         } else {
187                 if (yych <= 'h') {
188                         if (yych <= 'a') {
189                                 if (yych == '_') goto yy20;
190                                 if (yych <= '`') goto yy23;
191                                 goto yy20;
192                         } else {
193                                 if (yych <= 'b') goto yy8;
194                                 if (yych == 'd') goto yy11;
195                                 goto yy20;
196                         }
197                 } else {
198                         if (yych <= 's') {
199                                 if (yych <= 'i') goto yy18;
200                                 if (yych <= 'q') goto yy20;
201                                 if (yych <= 'r') goto yy10;
202                                 goto yy19;
203                         } else {
204                                 if (yych <= 'z') goto yy20;
205                                 if (yych == '|') goto yy16;
206                                 goto yy23;
207                         }
208                 }
209         }
210 yy2:
211         yyaccept = 0;
212         yych = *(q = ++p);
213         goto yy65;
214 yy3:
215         { token = INDENT;   break; }
216 yy4:
217         yyaccept = 1;
218         yych = *(q = ++p);
219         if (yych <= 0x00) goto yy5;
220         if (yych != '\r') goto yy60;
221 yy5:
222         { token = ERROR;    break; }
223 yy6:
224         ++p;
225 yy7:
226         { token = NEWLINE;  break; }
227 yy8:
228         ++p;
229         if ((yych = *p) == 'u') goto yy54;
230         goto yy25;
231 yy9:
232         { token = IDENT;    break; }
233 yy10:
234         yych = *++p;
235         if (yych == 'u') goto yy50;
236         goto yy25;
237 yy11:
238         yych = *++p;
239         if (yych == 'e') goto yy43;
240         goto yy25;
241 yy12:
242         ++p;
243         { token = EQUALS;   break; }
244 yy14:
245         ++p;
246         { token = COLON;    break; }
247 yy16:
248         ++p;
249         if ((yych = *p) == '|') goto yy41;
250         { token = PIPE;     break; }
251 yy18:
252         yych = *++p;
253         if (yych == 'n') goto yy34;
254         goto yy25;
255 yy19:
256         yych = *++p;
257         if (yych == 'u') goto yy26;
258         goto yy25;
259 yy20:
260         yych = *++p;
261         goto yy25;
262 yy21:
263         ++p;
264         { token = TEOF;     break; }
265 yy23:
266         yych = *++p;
267         goto yy5;
268 yy24:
269         ++p;
270         yych = *p;
271 yy25:
272         if (yybm[0+yych] & 32) {
273                 goto yy24;
274         }
275         goto yy9;
276 yy26:
277         yych = *++p;
278         if (yych != 'b') goto yy25;
279         yych = *++p;
280         if (yych != 'n') goto yy25;
281         yych = *++p;
282         if (yych != 'i') goto yy25;
283         yych = *++p;
284         if (yych != 'n') goto yy25;
285         yych = *++p;
286         if (yych != 'j') goto yy25;
287         yych = *++p;
288         if (yych != 'a') goto yy25;
289         ++p;
290         if (yybm[0+(yych = *p)] & 32) {
291                 goto yy24;
292         }
293         { token = SUBNINJA; break; }
294 yy34:
295         yych = *++p;
296         if (yych != 'c') goto yy25;
297         yych = *++p;
298         if (yych != 'l') goto yy25;
299         yych = *++p;
300         if (yych != 'u') goto yy25;
301         yych = *++p;
302         if (yych != 'd') goto yy25;
303         yych = *++p;
304         if (yych != 'e') goto yy25;
305         ++p;
306         if (yybm[0+(yych = *p)] & 32) {
307                 goto yy24;
308         }
309         { token = INCLUDE;  break; }
310 yy41:
311         ++p;
312         { token = PIPE2;    break; }
313 yy43:
314         yych = *++p;
315         if (yych != 'f') goto yy25;
316         yych = *++p;
317         if (yych != 'a') goto yy25;
318         yych = *++p;
319         if (yych != 'u') goto yy25;
320         yych = *++p;
321         if (yych != 'l') goto yy25;
322         yych = *++p;
323         if (yych != 't') goto yy25;
324         ++p;
325         if (yybm[0+(yych = *p)] & 32) {
326                 goto yy24;
327         }
328         { token = DEFAULT;  break; }
329 yy50:
330         yych = *++p;
331         if (yych != 'l') goto yy25;
332         yych = *++p;
333         if (yych != 'e') goto yy25;
334         ++p;
335         if (yybm[0+(yych = *p)] & 32) {
336                 goto yy24;
337         }
338         { token = RULE;     break; }
339 yy54:
340         yych = *++p;
341         if (yych != 'i') goto yy25;
342         yych = *++p;
343         if (yych != 'l') goto yy25;
344         yych = *++p;
345         if (yych != 'd') goto yy25;
346         ++p;
347         if (yybm[0+(yych = *p)] & 32) {
348                 goto yy24;
349         }
350         { token = BUILD;    break; }
351 yy59:
352         ++p;
353         yych = *p;
354 yy60:
355         if (yybm[0+yych] & 64) {
356                 goto yy59;
357         }
358         if (yych <= 0x00) goto yy61;
359         if (yych <= '\f') goto yy62;
360 yy61:
361         p = q;
362         if (yyaccept <= 0) {
363                 goto yy3;
364         } else {
365                 goto yy5;
366         }
367 yy62:
368         ++p;
369         { continue; }
370 yy64:
371         yyaccept = 0;
372         q = ++p;
373         yych = *p;
374 yy65:
375         if (yybm[0+yych] & 128) {
376                 goto yy64;
377         }
378         if (yych == '\n') goto yy66;
379         if (yych == '#') goto yy59;
380         goto yy3;
381 yy66:
382         ++p;
383         yych = *p;
384         goto yy7;
385 }
386
387   }
388
389   last_token_ = start;
390   ofs_ = p;
391   if (token != NEWLINE && token != TEOF)
392     EatWhitespace();
393   return token;
394 }
395
396 bool Lexer::PeekToken(Token token) {
397   Token t = ReadToken();
398   if (t == token)
399     return true;
400   UnreadToken();
401   return false;
402 }
403
404 void Lexer::EatWhitespace() {
405   const char* p = ofs_;
406   for (;;) {
407     ofs_ = p;
408     
409 {
410         unsigned char yych;
411         static const unsigned char yybm[] = {
412                   0,   0,   0,   0,   0,   0,   0,   0, 
413                   0,   0,   0,   0,   0,   0,   0,   0, 
414                   0,   0,   0,   0,   0,   0,   0,   0, 
415                   0,   0,   0,   0,   0,   0,   0,   0, 
416                 128,   0,   0,   0,   0,   0,   0,   0, 
417                   0,   0,   0,   0,   0,   0,   0,   0, 
418                   0,   0,   0,   0,   0,   0,   0,   0, 
419                   0,   0,   0,   0,   0,   0,   0,   0, 
420                   0,   0,   0,   0,   0,   0,   0,   0, 
421                   0,   0,   0,   0,   0,   0,   0,   0, 
422                   0,   0,   0,   0,   0,   0,   0,   0, 
423                   0,   0,   0,   0,   0,   0,   0,   0, 
424                   0,   0,   0,   0,   0,   0,   0,   0, 
425                   0,   0,   0,   0,   0,   0,   0,   0, 
426                   0,   0,   0,   0,   0,   0,   0,   0, 
427                   0,   0,   0,   0,   0,   0,   0,   0, 
428                   0,   0,   0,   0,   0,   0,   0,   0, 
429                   0,   0,   0,   0,   0,   0,   0,   0, 
430                   0,   0,   0,   0,   0,   0,   0,   0, 
431                   0,   0,   0,   0,   0,   0,   0,   0, 
432                   0,   0,   0,   0,   0,   0,   0,   0, 
433                   0,   0,   0,   0,   0,   0,   0,   0, 
434                   0,   0,   0,   0,   0,   0,   0,   0, 
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                   0,   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         };
445         yych = *p;
446         if (yych <= ' ') {
447                 if (yych <= 0x00) goto yy73;
448                 if (yych <= 0x1F) goto yy75;
449         } else {
450                 if (yych == '$') goto yy71;
451                 goto yy75;
452         }
453         ++p;
454         yych = *p;
455         goto yy79;
456 yy70:
457         { continue; }
458 yy71:
459         ++p;
460         if ((yych = *p) == '\n') goto yy76;
461 yy72:
462         { break; }
463 yy73:
464         ++p;
465         { break; }
466 yy75:
467         yych = *++p;
468         goto yy72;
469 yy76:
470         ++p;
471         { continue; }
472 yy78:
473         ++p;
474         yych = *p;
475 yy79:
476         if (yybm[0+yych] & 128) {
477                 goto yy78;
478         }
479         goto yy70;
480 }
481
482   }
483 }
484
485 bool Lexer::ReadIdent(string* out) {
486   const char* p = ofs_;
487   for (;;) {
488     const char* start = p;
489     
490 {
491         unsigned char yych;
492         static const unsigned char yybm[] = {
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, 128, 128,   0, 
499                 128, 128, 128, 128, 128, 128, 128, 128, 
500                 128, 128,   0,   0,   0,   0,   0,   0, 
501                   0, 128, 128, 128, 128, 128, 128, 128, 
502                 128, 128, 128, 128, 128, 128, 128, 128, 
503                 128, 128, 128, 128, 128, 128, 128, 128, 
504                 128, 128, 128,   0,   0,   0,   0, 128, 
505                   0, 128, 128, 128, 128, 128, 128, 128, 
506                 128, 128, 128, 128, 128, 128, 128, 128, 
507                 128, 128, 128, 128, 128, 128, 128, 128, 
508                 128, 128, 128,   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                   0,   0,   0,   0,   0,   0,   0,   0, 
513                   0,   0,   0,   0,   0,   0,   0,   0, 
514                   0,   0,   0,   0,   0,   0,   0,   0, 
515                   0,   0,   0,   0,   0,   0,   0,   0, 
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,   0,   0,   0, 
522                   0,   0,   0,   0,   0,   0,   0,   0, 
523                   0,   0,   0,   0,   0,   0,   0,   0, 
524                   0,   0,   0,   0,   0,   0,   0,   0, 
525         };
526         yych = *p;
527         if (yych <= '@') {
528                 if (yych <= '.') {
529                         if (yych <= ',') goto yy84;
530                 } else {
531                         if (yych <= '/') goto yy84;
532                         if (yych >= ':') goto yy84;
533                 }
534         } else {
535                 if (yych <= '_') {
536                         if (yych <= 'Z') goto yy82;
537                         if (yych <= '^') goto yy84;
538                 } else {
539                         if (yych <= '`') goto yy84;
540                         if (yych >= '{') goto yy84;
541                 }
542         }
543 yy82:
544         ++p;
545         yych = *p;
546         goto yy87;
547 yy83:
548         {
549       out->assign(start, p - start);
550       break;
551     }
552 yy84:
553         ++p;
554         { return false; }
555 yy86:
556         ++p;
557         yych = *p;
558 yy87:
559         if (yybm[0+yych] & 128) {
560                 goto yy86;
561         }
562         goto yy83;
563 }
564
565   }
566   ofs_ = p;
567   EatWhitespace();
568   return true;
569 }
570
571 bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) {
572   const char* p = ofs_;
573   const char* q;
574   const char* start;
575   for (;;) {
576     start = p;
577     
578 {
579         unsigned char yych;
580         static const unsigned char yybm[] = {
581                   0, 128, 128, 128, 128, 128, 128, 128, 
582                 128, 128,   0, 128, 128,   0, 128, 128, 
583                 128, 128, 128, 128, 128, 128, 128, 128, 
584                 128, 128, 128, 128, 128, 128, 128, 128, 
585                  16, 128, 128, 128,   0, 128, 128, 128, 
586                 128, 128, 128, 128, 128, 224, 160, 128, 
587                 224, 224, 224, 224, 224, 224, 224, 224, 
588                 224, 224,   0, 128, 128, 128, 128, 128, 
589                 128, 224, 224, 224, 224, 224, 224, 224, 
590                 224, 224, 224, 224, 224, 224, 224, 224, 
591                 224, 224, 224, 224, 224, 224, 224, 224, 
592                 224, 224, 224, 128, 128, 128, 128, 224, 
593                 128, 224, 224, 224, 224, 224, 224, 224, 
594                 224, 224, 224, 224, 224, 224, 224, 224, 
595                 224, 224, 224, 224, 224, 224, 224, 224, 
596                 224, 224, 224, 128,   0, 128, 128, 128, 
597                 128, 128, 128, 128, 128, 128, 128, 128, 
598                 128, 128, 128, 128, 128, 128, 128, 128, 
599                 128, 128, 128, 128, 128, 128, 128, 128, 
600                 128, 128, 128, 128, 128, 128, 128, 128, 
601                 128, 128, 128, 128, 128, 128, 128, 128, 
602                 128, 128, 128, 128, 128, 128, 128, 128, 
603                 128, 128, 128, 128, 128, 128, 128, 128, 
604                 128, 128, 128, 128, 128, 128, 128, 128, 
605                 128, 128, 128, 128, 128, 128, 128, 128, 
606                 128, 128, 128, 128, 128, 128, 128, 128, 
607                 128, 128, 128, 128, 128, 128, 128, 128, 
608                 128, 128, 128, 128, 128, 128, 128, 128, 
609                 128, 128, 128, 128, 128, 128, 128, 128, 
610                 128, 128, 128, 128, 128, 128, 128, 128, 
611                 128, 128, 128, 128, 128, 128, 128, 128, 
612                 128, 128, 128, 128, 128, 128, 128, 128, 
613         };
614         yych = *p;
615         if (yych <= ' ') {
616                 if (yych <= '\n') {
617                         if (yych <= 0x00) goto yy96;
618                         if (yych >= '\n') goto yy92;
619                 } else {
620                         if (yych == '\r') goto yy98;
621                         if (yych >= ' ') goto yy92;
622                 }
623         } else {
624                 if (yych <= '9') {
625                         if (yych == '$') goto yy94;
626                 } else {
627                         if (yych <= ':') goto yy92;
628                         if (yych == '|') goto yy92;
629                 }
630         }
631         ++p;
632         yych = *p;
633         goto yy121;
634 yy91:
635         {
636       eval->AddText(StringPiece(start, p - start));
637       continue;
638     }
639 yy92:
640         ++p;
641         {
642       if (path) {
643         p = start;
644         break;
645       } else {
646         if (*start == '\n')
647           break;
648         eval->AddText(StringPiece(start, 1));
649         continue;
650       }
651     }
652 yy94:
653         ++p;
654         if ((yych = *p) <= '/') {
655                 if (yych <= ' ') {
656                         if (yych == '\n') goto yy110;
657                         if (yych <= 0x1F) goto yy99;
658                         goto yy101;
659                 } else {
660                         if (yych <= '$') {
661                                 if (yych <= '#') goto yy99;
662                                 goto yy103;
663                         } else {
664                                 if (yych == '-') goto yy105;
665                                 goto yy99;
666                         }
667                 }
668         } else {
669                 if (yych <= '^') {
670                         if (yych <= ':') {
671                                 if (yych <= '9') goto yy105;
672                                 goto yy107;
673                         } else {
674                                 if (yych <= '@') goto yy99;
675                                 if (yych <= 'Z') goto yy105;
676                                 goto yy99;
677                         }
678                 } else {
679                         if (yych <= '`') {
680                                 if (yych <= '_') goto yy105;
681                                 goto yy99;
682                         } else {
683                                 if (yych <= 'z') goto yy105;
684                                 if (yych <= '{') goto yy109;
685                                 goto yy99;
686                         }
687                 }
688         }
689 yy95:
690         {
691       last_token_ = start;
692       return Error("lexing error", err);
693     }
694 yy96:
695         ++p;
696         {
697       last_token_ = start;
698       return Error("unexpected EOF", err);
699     }
700 yy98:
701         yych = *++p;
702         goto yy95;
703 yy99:
704         ++p;
705 yy100:
706         {
707       last_token_ = start;
708       return Error("bad $-escape (literal $ must be written as $$)", err);
709     }
710 yy101:
711         ++p;
712         {
713       eval->AddText(StringPiece(" ", 1));
714       continue;
715     }
716 yy103:
717         ++p;
718         {
719       eval->AddText(StringPiece("$", 1));
720       continue;
721     }
722 yy105:
723         ++p;
724         yych = *p;
725         goto yy119;
726 yy106:
727         {
728       eval->AddSpecial(StringPiece(start + 1, p - start - 1));
729       continue;
730     }
731 yy107:
732         ++p;
733         {
734       eval->AddText(StringPiece(":", 1));
735       continue;
736     }
737 yy109:
738         yych = *(q = ++p);
739         if (yybm[0+yych] & 32) {
740                 goto yy113;
741         }
742         goto yy100;
743 yy110:
744         ++p;
745         yych = *p;
746         if (yybm[0+yych] & 16) {
747                 goto yy110;
748         }
749         {
750       continue;
751     }
752 yy113:
753         ++p;
754         yych = *p;
755         if (yybm[0+yych] & 32) {
756                 goto yy113;
757         }
758         if (yych == '}') goto yy116;
759         p = q;
760         goto yy100;
761 yy116:
762         ++p;
763         {
764       eval->AddSpecial(StringPiece(start + 2, p - start - 3));
765       continue;
766     }
767 yy118:
768         ++p;
769         yych = *p;
770 yy119:
771         if (yybm[0+yych] & 64) {
772                 goto yy118;
773         }
774         goto yy106;
775 yy120:
776         ++p;
777         yych = *p;
778 yy121:
779         if (yybm[0+yych] & 128) {
780                 goto yy120;
781         }
782         goto yy91;
783 }
784
785   }
786   last_token_ = start;
787   ofs_ = p;
788   if (path)
789     EatWhitespace();
790   // Non-path strings end in newlines, so there's no whitespace to eat.
791   return true;
792 }