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