github.com/maruel/nin@v0.0.0-20220112143044-f35891e3ce7e/src/lexer.cc (about)

     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  
    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  
    64  Lexer::Lexer(const char* input) {
    65    Start("input", input);
    66  }
    67  
    68  void Lexer::Start(StringPiece filename, StringPiece input) {
    69    filename_ = filename;
    70    input_ = input;
    71    ofs_ = input_.str_;
    72    last_token_ = NULL;
    73  }
    74  
    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  
    97  const char* Lexer::TokenErrorHint(Token expected) {
    98    switch (expected) {
    99    case COLON:
   100      return " ($ also escapes ':')";
   101    default:
   102      return "";
   103    }
   104  }
   105  
   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  
   116  void Lexer::UnreadToken() {
   117    ofs_ = last_token_;
   118  }
   119  
   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  
   463  bool Lexer::PeekToken(Token token) {
   464    Token t = ReadToken();
   465    if (t == token)
   466      return true;
   467    UnreadToken();
   468    return false;
   469  }
   470  
   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  
   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  
   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  }