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