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
23 using namespace std;
24
Error(const string & message,string * err)25 bool 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
Lexer(const char * input)64 Lexer::Lexer(const char* input) {
65 Start("input", input);
66 }
67
Start(StringPiece filename,StringPiece input)68 void Lexer::Start(StringPiece filename, StringPiece input) {
69 filename_ = filename;
70 input_ = input;
71 ofs_ = input_.str_;
72 last_token_ = NULL;
73 }
74
TokenName(Token t)75 const 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
TokenErrorHint(Token expected)97 const char* Lexer::TokenErrorHint(Token expected) {
98 switch (expected) {
99 case COLON:
100 return " ($ also escapes ':')";
101 default:
102 return "";
103 }
104 }
105
DescribeLastError()106 string 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
UnreadToken()116 void Lexer::UnreadToken() {
117 ofs_ = last_token_;
118 }
119
ReadToken()120 Lexer::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 }
223 yy2:
224 ++p;
225 { token = TEOF; break; }
226 yy4:
227 ++p;
228 yy5:
229 { token = ERROR; break; }
230 yy6:
231 ++p;
232 { token = NEWLINE; break; }
233 yy8:
234 yych = *++p;
235 if (yych == '\n') goto yy28;
236 goto yy5;
237 yy9:
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 }
249 yy11:
250 { token = INDENT; break; }
251 yy12:
252 yyaccept = 1;
253 yych = *(q = ++p);
254 if (yych <= 0x00) goto yy5;
255 goto yy33;
256 yy13:
257 yych = *++p;
258 yy14:
259 if (yybm[0+yych] & 64) {
260 goto yy13;
261 }
262 { token = IDENT; break; }
263 yy16:
264 ++p;
265 { token = COLON; break; }
266 yy18:
267 ++p;
268 { token = EQUALS; break; }
269 yy20:
270 yych = *++p;
271 if (yych == 'u') goto yy36;
272 goto yy14;
273 yy21:
274 yych = *++p;
275 if (yych == 'e') goto yy37;
276 goto yy14;
277 yy22:
278 yych = *++p;
279 if (yych == 'n') goto yy38;
280 goto yy14;
281 yy23:
282 yych = *++p;
283 if (yych == 'o') goto yy39;
284 goto yy14;
285 yy24:
286 yych = *++p;
287 if (yych == 'u') goto yy40;
288 goto yy14;
289 yy25:
290 yych = *++p;
291 if (yych == 'u') goto yy41;
292 goto yy14;
293 yy26:
294 yych = *++p;
295 if (yych == '@') goto yy42;
296 if (yych == '|') goto yy44;
297 { token = PIPE; break; }
298 yy28:
299 ++p;
300 { token = NEWLINE; break; }
301 yy30:
302 yych = *++p;
303 if (yych == '\n') goto yy28;
304 yy31:
305 p = q;
306 if (yyaccept == 0) {
307 goto yy11;
308 } else {
309 goto yy5;
310 }
311 yy32:
312 yych = *++p;
313 yy33:
314 if (yybm[0+yych] & 128) {
315 goto yy32;
316 }
317 if (yych <= 0x00) goto yy31;
318 ++p;
319 { continue; }
320 yy36:
321 yych = *++p;
322 if (yych == 'i') goto yy46;
323 goto yy14;
324 yy37:
325 yych = *++p;
326 if (yych == 'f') goto yy47;
327 goto yy14;
328 yy38:
329 yych = *++p;
330 if (yych == 'c') goto yy48;
331 goto yy14;
332 yy39:
333 yych = *++p;
334 if (yych == 'o') goto yy49;
335 goto yy14;
336 yy40:
337 yych = *++p;
338 if (yych == 'l') goto yy50;
339 goto yy14;
340 yy41:
341 yych = *++p;
342 if (yych == 'b') goto yy51;
343 goto yy14;
344 yy42:
345 ++p;
346 { token = PIPEAT; break; }
347 yy44:
348 ++p;
349 { token = PIPE2; break; }
350 yy46:
351 yych = *++p;
352 if (yych == 'l') goto yy52;
353 goto yy14;
354 yy47:
355 yych = *++p;
356 if (yych == 'a') goto yy53;
357 goto yy14;
358 yy48:
359 yych = *++p;
360 if (yych == 'l') goto yy54;
361 goto yy14;
362 yy49:
363 yych = *++p;
364 if (yych == 'l') goto yy55;
365 goto yy14;
366 yy50:
367 yych = *++p;
368 if (yych == 'e') goto yy57;
369 goto yy14;
370 yy51:
371 yych = *++p;
372 if (yych == 'n') goto yy59;
373 goto yy14;
374 yy52:
375 yych = *++p;
376 if (yych == 'd') goto yy60;
377 goto yy14;
378 yy53:
379 yych = *++p;
380 if (yych == 'u') goto yy62;
381 goto yy14;
382 yy54:
383 yych = *++p;
384 if (yych == 'u') goto yy63;
385 goto yy14;
386 yy55:
387 yych = *++p;
388 if (yybm[0+yych] & 64) {
389 goto yy13;
390 }
391 { token = POOL; break; }
392 yy57:
393 yych = *++p;
394 if (yybm[0+yych] & 64) {
395 goto yy13;
396 }
397 { token = RULE; break; }
398 yy59:
399 yych = *++p;
400 if (yych == 'i') goto yy64;
401 goto yy14;
402 yy60:
403 yych = *++p;
404 if (yybm[0+yych] & 64) {
405 goto yy13;
406 }
407 { token = BUILD; break; }
408 yy62:
409 yych = *++p;
410 if (yych == 'l') goto yy65;
411 goto yy14;
412 yy63:
413 yych = *++p;
414 if (yych == 'd') goto yy66;
415 goto yy14;
416 yy64:
417 yych = *++p;
418 if (yych == 'n') goto yy67;
419 goto yy14;
420 yy65:
421 yych = *++p;
422 if (yych == 't') goto yy68;
423 goto yy14;
424 yy66:
425 yych = *++p;
426 if (yych == 'e') goto yy70;
427 goto yy14;
428 yy67:
429 yych = *++p;
430 if (yych == 'j') goto yy72;
431 goto yy14;
432 yy68:
433 yych = *++p;
434 if (yybm[0+yych] & 64) {
435 goto yy13;
436 }
437 { token = DEFAULT; break; }
438 yy70:
439 yych = *++p;
440 if (yybm[0+yych] & 64) {
441 goto yy13;
442 }
443 { token = INCLUDE; break; }
444 yy72:
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
PeekToken(Token token)463 bool Lexer::PeekToken(Token token) {
464 Token t = ReadToken();
465 if (t == token)
466 return true;
467 UnreadToken();
468 return false;
469 }
470
EatWhitespace()471 void 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;
520 yy77:
521 ++p;
522 { break; }
523 yy79:
524 ++p;
525 yy80:
526 { break; }
527 yy81:
528 yych = *++p;
529 if (yybm[0+yych] & 128) {
530 goto yy81;
531 }
532 { continue; }
533 yy84:
534 yych = *(q = ++p);
535 if (yych == '\n') goto yy85;
536 if (yych == '\r') goto yy87;
537 goto yy80;
538 yy85:
539 ++p;
540 { continue; }
541 yy87:
542 yych = *++p;
543 if (yych == '\n') goto yy89;
544 p = q;
545 goto yy80;
546 yy89:
547 ++p;
548 { continue; }
549 }
550
551 }
552 }
553
ReadIdent(string * out)554 bool 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 }
605 yy95:
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
ReadEvalString(EvalString * eval,bool path,string * err)623 bool 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 }
679 yy100:
680 ++p;
681 {
682 last_token_ = start;
683 return Error("unexpected EOF", err);
684 }
685 yy102:
686 yych = *++p;
687 if (yybm[0+yych] & 16) {
688 goto yy102;
689 }
690 {
691 eval->AddText(StringPiece(start, p - start));
692 continue;
693 }
694 yy105:
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 }
707 yy107:
708 yych = *++p;
709 if (yych == '\n') goto yy110;
710 {
711 last_token_ = start;
712 return Error(DescribeLastError(), err);
713 }
714 yy109:
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 }
739 yy110:
740 ++p;
741 {
742 if (path)
743 p = start;
744 break;
745 }
746 yy112:
747 ++p;
748 yy113:
749 {
750 last_token_ = start;
751 return Error("bad $-escape (literal $ must be written as $$)", err);
752 }
753 yy114:
754 yych = *++p;
755 if (yybm[0+yych] & 32) {
756 goto yy114;
757 }
758 {
759 continue;
760 }
761 yy117:
762 yych = *++p;
763 if (yych == '\n') goto yy128;
764 goto yy113;
765 yy118:
766 ++p;
767 {
768 eval->AddText(StringPiece(" ", 1));
769 continue;
770 }
771 yy120:
772 ++p;
773 {
774 eval->AddText(StringPiece("$", 1));
775 continue;
776 }
777 yy122:
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 }
786 yy125:
787 ++p;
788 {
789 eval->AddText(StringPiece(":", 1));
790 continue;
791 }
792 yy127:
793 yych = *(q = ++p);
794 if (yybm[0+yych] & 128) {
795 goto yy131;
796 }
797 goto yy113;
798 yy128:
799 yych = *++p;
800 if (yych == ' ') goto yy128;
801 {
802 continue;
803 }
804 yy131:
805 yych = *++p;
806 if (yybm[0+yych] & 128) {
807 goto yy131;
808 }
809 if (yych == '}') goto yy134;
810 p = q;
811 goto yy113;
812 yy134:
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