blob: cba0ecfcabef607d2673d0335a38d590646382da [file] [log] [blame]
/* Generated by re2c 1.3 */
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "lexer.h"
#include <stdio.h>
#include "eval_env.h"
#include "graph.h"
#include "util.h"
size_t AdvanceToNextManifestChunk(StringPiece content, size_t idx) {
assert(idx <= content.size());
// Iterate over each LF in the manifest, starting at the given index.
while (true) {
const void* next_line = memchr(content.data() + idx, '\n',
content.size() - idx);
if (next_line == nullptr) {
break;
}
idx = static_cast<const char*>(next_line) - content.data();
++idx; // step over the LF
// The line must not be preceded by a line continuator. This logic can
// filter out more split candidates than strictly necessary:
// - The preceding line could have a comment that ends with a "$": "# $\n"
// - The preceding line could end with an escaped-dollar: "X=$$\n"
if ((idx >= 2 && content.substr(idx - 2, 2) == "$\n") ||
(idx >= 3 && content.substr(idx - 3, 3) == "$\r\n")) {
continue;
}
// Skip an indented line or a comment line, either of which could be part of
// an earlier declaration. Ninja allows unindented comments (as well as
// indented comments) inside a binding block, e.g.:
//
// build foo: cc
// # comment-line
// pool = link_pool
//
// Ninja doesn't allow blank lines in a binding block. This code could
// probably allow a chunk to start with a blank line, but it seems better if
// it doesn't.
if (idx >= content.size() ||
content[idx] == ' ' || content[idx] == '#' ||
content[idx] == '\r' || content[idx] == '\n') {
continue;
}
return idx;
}
return content.size();
}
bool DecorateErrorWithLocation(const std::string& filename,
const char* file_start,
size_t file_offset,
const std::string& message,
std::string* err) {
// Make a copy in case message and err alias.
std::string message_tmp = message;
// Compute line/column.
int line = 1;
const char* line_start = file_start;
const char* file_pos = file_start + file_offset;
for (const char* p = line_start; p < file_pos; ++p) {
if (*p == '\n') {
++line;
line_start = p + 1;
}
}
int col = (int)(file_pos - line_start);
char buf[1024];
snprintf(buf, sizeof(buf), "%s:%d: ", filename.c_str(), line);
*err = buf;
*err += message_tmp + "\n";
// Add some context to the message.
const int kTruncateColumn = 72;
if (col > 0 && col < kTruncateColumn) {
int len;
bool truncated = true;
for (len = 0; len < kTruncateColumn; ++len) {
if (line_start[len] == 0 || line_start[len] == '\n') {
truncated = false;
break;
}
}
*err += string(line_start, len);
if (truncated)
*err += "...";
*err += "\n";
*err += string(col, ' ');
*err += "^ near here";
}
return false;
}
bool Lexer::Error(const std::string& message, std::string* err) {
return DecorateErrorWithLocation(filename_, input_.data(),
GetLastTokenOffset(), message, err);
}
bool Lexer::UnexpectedNulError(const char* pos, std::string* err) {
assert(*pos == '\0');
const char* msg = (pos == EndOfFile()) ? "unexpected EOF"
: "unexpected NUL byte";
return Error(msg, err);
}
const char* Lexer::TokenName(Token t) {
switch (t) {
case ERROR: return "lexing error";
case BUILD: return "'build'";
case CHDIR: return "'chdir'";
case COLON: return "':'";
case DEFAULT: return "'default'";
case EQUALS: return "'='";
case IDENT: return "identifier";
case INCLUDE: return "'include'";
case INDENT: return "indent";
case NEWLINE: return "newline";
case PIPE2: return "'||'";
case PIPE: return "'|'";
case PIPEAT: return "'|@'";
case POOL: return "'pool'";
case RULE: return "'rule'";
case SUBNINJA: return "'subninja'";
case TNUL: return "nul byte";
case TEOF: return "eof";
}
return NULL; // not reached
}
const char* Lexer::TokenErrorHint(Token expected) {
switch (expected) {
case COLON:
return " ($ also escapes ':')";
default:
return "";
}
}
string Lexer::DescribeLastError() {
if (last_token_) {
switch (last_token_[0]) {
case '\t':
return "tabs are not allowed, use spaces";
}
}
return "lexing error";
}
void Lexer::UnreadToken() {
ofs_ = last_token_;
}
Lexer::Token Lexer::ReadToken() {
const char* p = ofs_;
const char* q;
const char* r;
const char* start;
Lexer::Token token;
for (;;) {
start = p;
{
unsigned char yych;
unsigned int yyaccept = 0;
static const unsigned char yybm[] = {
0, 128, 128, 128, 128, 128, 128, 128,
128, 128, 0, 128, 128, 0, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
160, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 192, 192, 128,
192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 128, 128, 128, 128, 128, 128,
128, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 128, 128, 128, 128, 192,
128, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
};
yych = *p;
if (yybm[0+yych] & 32) {
goto yy6;
}
if (yych <= '^') {
if (yych <= ',') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy1;
if (yych == '\n') goto yy4;
goto yy2;
} else {
if (yych <= '\r') goto yy5;
if (yych == '#') goto yy8;
goto yy2;
}
} else {
if (yych <= ':') {
if (yych == '/') goto yy2;
if (yych <= '9') goto yy9;
goto yy11;
} else {
if (yych <= '=') {
if (yych <= '<') goto yy2;
goto yy12;
} else {
if (yych <= '@') goto yy2;
if (yych <= 'Z') goto yy9;
goto yy2;
}
}
}
} else {
if (yych <= 'i') {
if (yych <= 'b') {
if (yych == '`') goto yy2;
if (yych <= 'a') goto yy9;
goto yy13;
} else {
if (yych <= 'c') goto yy14;
if (yych <= 'd') goto yy15;
if (yych <= 'h') goto yy9;
goto yy16;
}
} else {
if (yych <= 'r') {
if (yych == 'p') goto yy17;
if (yych <= 'q') goto yy9;
goto yy18;
} else {
if (yych <= 'z') {
if (yych <= 's') goto yy19;
goto yy9;
} else {
if (yych == '|') goto yy20;
goto yy2;
}
}
}
}
yy1:
++p;
{ token = (start == EndOfFile()) ? TEOF : TNUL; break; }
yy2:
++p;
yy3:
{ token = ERROR; break; }
yy4:
++p;
{ token = NEWLINE; break; }
yy5:
yych = *++p;
if (yych == '\n') goto yy4;
goto yy3;
yy6:
yyaccept = 0;
yych = *(q = ++p);
if (yybm[0+yych] & 32) {
goto yy6;
}
if (yych <= '\f') {
if (yych == '\n') goto yy4;
} else {
if (yych <= '\r') goto yy21;
if (yych == '#') goto yy23;
}
yy7:
{ token = INDENT; break; }
yy8:
yyaccept = 1;
yych = *(q = ++p);
if (yych <= 0x00) goto yy3;
goto yy24;
yy9:
yych = *++p;
yy10:
if (yybm[0+yych] & 64) {
goto yy9;
}
{ token = IDENT; break; }
yy11:
++p;
{ token = COLON; break; }
yy12:
++p;
{ token = EQUALS; break; }
yy13:
yych = *++p;
if (yych == 'u') goto yy27;
goto yy10;
yy14:
yych = *++p;
if (yych == 'h') goto yy28;
goto yy10;
yy15:
yych = *++p;
if (yych == 'e') goto yy29;
goto yy10;
yy16:
yych = *++p;
if (yych == 'n') goto yy30;
goto yy10;
yy17:
yych = *++p;
if (yych == 'o') goto yy31;
goto yy10;
yy18:
yych = *++p;
if (yych == 'u') goto yy32;
goto yy10;
yy19:
yych = *++p;
if (yych == 'u') goto yy33;
goto yy10;
yy20:
yych = *++p;
if (yych == '@') goto yy34;
if (yych == '|') goto yy35;
{ token = PIPE; break; }
yy21:
yych = *++p;
if (yych == '\n') goto yy4;
yy22:
p = q;
if (yyaccept == 0) {
goto yy7;
} else {
goto yy3;
}
yy23:
yych = *++p;
yy24:
if (yybm[0+yych] & 128) {
goto yy23;
}
if (yych <= 0x00) goto yy22;
if (yych >= '\v') {
r = p;
goto yy26;
}
r = p;
yy25:
++p;
p = r;
{ continue; }
yy26:
yych = *++p;
if (yych == '\n') goto yy25;
goto yy22;
yy27:
yych = *++p;
if (yych == 'i') goto yy36;
goto yy10;
yy28:
yych = *++p;
if (yych == 'd') goto yy37;
goto yy10;
yy29:
yych = *++p;
if (yych == 'f') goto yy38;
goto yy10;
yy30:
yych = *++p;
if (yych == 'c') goto yy39;
goto yy10;
yy31:
yych = *++p;
if (yych == 'o') goto yy40;
goto yy10;
yy32:
yych = *++p;
if (yych == 'l') goto yy41;
goto yy10;
yy33:
yych = *++p;
if (yych == 'b') goto yy42;
goto yy10;
yy34:
++p;
{ token = PIPEAT; break; }
yy35:
++p;
{ token = PIPE2; break; }
yy36:
yych = *++p;
if (yych == 'l') goto yy43;
goto yy10;
yy37:
yych = *++p;
if (yych == 'i') goto yy44;
goto yy10;
yy38:
yych = *++p;
if (yych == 'a') goto yy45;
goto yy10;
yy39:
yych = *++p;
if (yych == 'l') goto yy46;
goto yy10;
yy40:
yych = *++p;
if (yych == 'l') goto yy47;
goto yy10;
yy41:
yych = *++p;
if (yych == 'e') goto yy48;
goto yy10;
yy42:
yych = *++p;
if (yych == 'n') goto yy49;
goto yy10;
yy43:
yych = *++p;
if (yych == 'd') goto yy50;
goto yy10;
yy44:
yych = *++p;
if (yych == 'r') goto yy51;
goto yy10;
yy45:
yych = *++p;
if (yych == 'u') goto yy52;
goto yy10;
yy46:
yych = *++p;
if (yych == 'u') goto yy53;
goto yy10;
yy47:
yych = *++p;
if (yybm[0+yych] & 64) {
goto yy9;
}
{ token = POOL; break; }
yy48:
yych = *++p;
if (yybm[0+yych] & 64) {
goto yy9;
}
{ token = RULE; break; }
yy49:
yych = *++p;
if (yych == 'i') goto yy54;
goto yy10;
yy50:
yych = *++p;
if (yybm[0+yych] & 64) {
goto yy9;
}
{ token = BUILD; break; }
yy51:
yych = *++p;
if (yybm[0+yych] & 64) {
goto yy9;
}
{ token = CHDIR; break; }
yy52:
yych = *++p;
if (yych == 'l') goto yy55;
goto yy10;
yy53:
yych = *++p;
if (yych == 'd') goto yy56;
goto yy10;
yy54:
yych = *++p;
if (yych == 'n') goto yy57;
goto yy10;
yy55:
yych = *++p;
if (yych == 't') goto yy58;
goto yy10;
yy56:
yych = *++p;
if (yych == 'e') goto yy59;
goto yy10;
yy57:
yych = *++p;
if (yych == 'j') goto yy60;
goto yy10;
yy58:
yych = *++p;
if (yybm[0+yych] & 64) {
goto yy9;
}
{ token = DEFAULT; break; }
yy59:
yych = *++p;
if (yybm[0+yych] & 64) {
goto yy9;
}
{ token = INCLUDE; break; }
yy60:
yych = *++p;
if (yych != 'a') goto yy10;
yych = *++p;
if (yybm[0+yych] & 64) {
goto yy9;
}
{ token = SUBNINJA; break; }
}
}
last_token_ = start;
ofs_ = p;
if (token != NEWLINE && token != TEOF)
EatWhitespace();
return token;
}
bool Lexer::PeekIndent() {
const char* p = ofs_;
const char* q;
const char* start;
for (;;) {
start = p;
{
unsigned char yych;
unsigned int yyaccept = 0;
static const unsigned char yybm[] = {
0, 128, 128, 128, 128, 128, 128, 128,
128, 128, 0, 128, 128, 0, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
192, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
};
yych = *p;
if (yybm[0+yych] & 64) {
goto yy65;
}
if (yych <= '\f') {
if (yych == '\n') goto yy63;
} else {
if (yych <= '\r') goto yy64;
if (yych == '#') goto yy67;
}
++p;
yy62:
{ last_token_ = ofs_ = start; return false; }
yy63:
++p;
{ last_token_ = ofs_ = start; return false; }
yy64:
yych = *++p;
if (yych == '\n') goto yy63;
goto yy62;
yy65:
yyaccept = 0;
yych = *(q = ++p);
if (yybm[0+yych] & 64) {
goto yy65;
}
if (yych <= '\f') {
if (yych == '\n') goto yy63;
} else {
if (yych <= '\r') goto yy68;
if (yych == '#') goto yy70;
}
yy66:
{ last_token_ = start; ofs_ = p; return true; }
yy67:
yyaccept = 1;
yych = *(q = ++p);
if (yych <= 0x00) goto yy62;
goto yy71;
yy68:
yych = *++p;
if (yych == '\n') goto yy63;
yy69:
p = q;
if (yyaccept == 0) {
goto yy66;
} else {
goto yy62;
}
yy70:
yych = *++p;
yy71:
if (yybm[0+yych] & 128) {
goto yy70;
}
if (yych <= 0x00) goto yy69;
if (yych >= '\v') goto yy73;
yy72:
++p;
{ continue; }
yy73:
yych = *++p;
if (yych == '\n') goto yy72;
goto yy69;
}
}
}
bool Lexer::PeekToken(Token token) {
Token t = ReadToken();
if (t == token)
return true;
UnreadToken();
return false;
}
void Lexer::EatWhitespace() {
const char* p = ofs_;
const char* q;
for (;;) {
ofs_ = p;
{
unsigned char yych;
static const unsigned char yybm[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
128, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
yych = *p;
if (yybm[0+yych] & 128) {
goto yy78;
}
if (yych <= 0x00) goto yy75;
if (yych == '$') goto yy79;
goto yy76;
yy75:
++p;
{ break; }
yy76:
++p;
yy77:
{ break; }
yy78:
yych = *++p;
if (yybm[0+yych] & 128) {
goto yy78;
}
{ continue; }
yy79:
yych = *(q = ++p);
if (yych == '\n') goto yy80;
if (yych == '\r') goto yy81;
goto yy77;
yy80:
++p;
{ continue; }
yy81:
yych = *++p;
if (yych == '\n') goto yy80;
p = q;
goto yy77;
}
}
}
bool Lexer::ReadIdent(StringPiece* out) {
const char* p = ofs_;
const char* start;
for (;;) {
start = p;
{
unsigned char yych;
static const unsigned char yybm[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 128, 128, 0,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 0, 0, 0, 0, 0, 0,
0, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 0, 0, 0, 0, 128,
0, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
yych = *p;
if (yybm[0+yych] & 128) {
goto yy83;
}
++p;
{
last_token_ = start;
return false;
}
yy83:
yych = *++p;
if (yybm[0+yych] & 128) {
goto yy83;
}
{
*out = StringPiece(start, p - start);
break;
}
}
}
last_token_ = start;
ofs_ = p;
EatWhitespace();
return true;
}
bool Lexer::ReadBindingValue(StringPiece* out, string* err) {
const char* p = ofs_;
const char* q;
const char* start;
for (;;) {
start = p;
{
unsigned char yych;
unsigned int yyaccept = 0;
static const unsigned char yybm[] = {
0, 64, 64, 64, 64, 64, 64, 64,
64, 64, 0, 64, 64, 0, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 0, 64, 64, 64,
64, 64, 64, 64, 64, 192, 192, 64,
192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 64, 64, 64, 64, 64, 64,
64, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 64, 64, 64, 64, 192,
64, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
};
yych = *p;
if (yybm[0+yych] & 64) {
goto yy86;
}
if (yych <= 0x00) goto yy85;
if (yych <= '\n') goto yy88;
if (yych <= '\r') goto yy89;
goto yy90;
yy85:
++p;
{
last_token_ = start;
return UnexpectedNulError(start, err);
}
yy86:
yyaccept = 0;
yych = *(q = ++p);
if (yybm[0+yych] & 64) {
goto yy86;
}
if (yych >= 0x0E) goto yy91;
yy87:
{
continue;
}
yy88:
++p;
{
break;
}
yy89:
yych = *++p;
if (yych == '\n') goto yy88;
{
last_token_ = start;
return Error(DescribeLastError(), err);
}
yy90:
yych = *++p;
if (yych <= '-') {
if (yych <= 0x1F) {
if (yych <= '\n') {
if (yych <= '\t') goto yy93;
goto yy86;
} else {
if (yych == '\r') goto yy95;
goto yy93;
}
} else {
if (yych <= '#') {
if (yych <= ' ') goto yy86;
goto yy93;
} else {
if (yych <= '$') goto yy86;
if (yych <= ',') goto yy93;
goto yy86;
}
}
} else {
if (yych <= '^') {
if (yych <= ':') {
if (yych <= '/') goto yy93;
goto yy86;
} else {
if (yych <= '@') goto yy93;
if (yych <= 'Z') goto yy86;
goto yy93;
}
} else {
if (yych <= '`') {
if (yych <= '_') goto yy86;
goto yy93;
} else {
if (yych <= 'z') goto yy86;
if (yych <= '{') goto yy96;
goto yy93;
}
}
}
yy91:
yych = *++p;
if (yych <= '-') {
if (yych <= 0x1F) {
if (yych <= '\n') {
if (yych >= '\n') goto yy86;
} else {
if (yych == '\r') goto yy97;
}
} else {
if (yych <= '#') {
if (yych <= ' ') goto yy86;
} else {
if (yych <= '$') goto yy86;
if (yych >= '-') goto yy86;
}
}
} else {
if (yych <= '^') {
if (yych <= ':') {
if (yych >= '0') goto yy86;
} else {
if (yych <= '@') goto yy92;
if (yych <= 'Z') goto yy86;
}
} else {
if (yych <= '`') {
if (yych <= '_') goto yy86;
} else {
if (yych <= 'z') goto yy86;
if (yych <= '{') goto yy98;
}
}
}
yy92:
p = q;
if (yyaccept == 0) {
goto yy87;
} else {
goto yy94;
}
yy93:
++p;
yy94:
{
last_token_ = start;
return Error("bad $-escape (literal $ must be written as $$)", err);
}
yy95:
yych = *++p;
if (yych == '\n') goto yy86;
goto yy94;
yy96:
yyaccept = 1;
yych = *(q = ++p);
if (yybm[0+yych] & 128) {
goto yy99;
}
goto yy94;
yy97:
yych = *++p;
if (yych == '\n') goto yy86;
goto yy92;
yy98:
yych = *++p;
if (yybm[0+yych] & 128) {
goto yy99;
}
goto yy92;
yy99:
yych = *++p;
if (yybm[0+yych] & 128) {
goto yy99;
}
if (yych == '}') goto yy86;
goto yy92;
}
}
*out = StringPiece(ofs_, p - ofs_);
last_token_ = start;
ofs_ = p;
// Non-path strings end in newlines, so there's no whitespace to eat.
return true;
}
StringPiece Lexer::PeekCanonicalPath() {
auto finish = [this](const char* start, const char* end) {
ofs_ = end;
EatWhitespace();
return StringPiece(start, end - start);
};
const char* p = ofs_;
const char* q;
const char* r;
last_token_ = ofs_;
do {
{
unsigned char yych;
static const unsigned char yybm[] = {
0, 128, 128, 128, 128, 128, 128, 128,
128, 128, 0, 128, 128, 0, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
0, 128, 128, 128, 0, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 0,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 0, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 0, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
};
yych = *p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy101;
if (yych != '\n') goto yy103;
} else {
if (yych <= '\r') goto yy101;
if (yych != ' ') goto yy103;
}
} else {
if (yych <= '/') {
if (yych <= '$') goto yy101;
if (yych <= '-') goto yy103;
if (yych <= '.') goto yy104;
goto yy105;
} else {
if (yych <= ':') {
if (yych <= '9') goto yy103;
} else {
if (yych != '|') goto yy103;
}
}
}
yy101:
++p;
yy102:
{ break; }
yy103:
yych = *(q = ++p);
if (yych <= 0x00) goto yy102;
if (yych == '$') goto yy102;
goto yy107;
yy104:
yych = *(q = ++p);
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy102;
if (yych == '\n') goto yy102;
goto yy106;
} else {
if (yych <= '\r') goto yy102;
if (yych == ' ') goto yy102;
goto yy106;
}
} else {
if (yych <= '/') {
if (yych <= '$') goto yy102;
if (yych <= '-') goto yy106;
if (yych <= '.') goto yy112;
goto yy113;
} else {
if (yych <= ':') {
if (yych <= '9') goto yy106;
goto yy102;
} else {
if (yych == '|') goto yy102;
goto yy106;
}
}
}
yy105:
yych = *(q = ++p);
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy102;
if (yych == '\n') goto yy102;
} else {
if (yych <= '\r') goto yy102;
if (yych == ' ') goto yy102;
}
} else {
if (yych <= '/') {
if (yych <= '$') goto yy102;
if (yych <= '-') goto yy106;
if (yych <= '.') goto yy114;
goto yy102;
} else {
if (yych <= ':') {
if (yych >= ':') goto yy102;
} else {
if (yych == '|') goto yy102;
}
}
}
yy106:
yych = *++p;
yy107:
if (yybm[0+yych] & 128) {
goto yy106;
}
if (yych <= '\r') {
if (yych <= 0x00) goto yy108;
if (yych <= '\n') {
r = p;
goto yy109;
}
r = p;
goto yy110;
} else {
if (yych <= ' ') {
r = p;
goto yy109;
}
if (yych <= '$') goto yy108;
if (yych <= '/') goto yy111;
r = p;
goto yy109;
}
yy108:
p = q;
goto yy102;
yy109:
++p;
p = r;
{ return finish(ofs_, p); }
yy110:
yych = *++p;
if (yych == '\n') goto yy109;
goto yy108;
yy111:
yych = *++p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy108;
if (yych == '\n') goto yy108;
goto yy106;
} else {
if (yych <= '\r') goto yy108;
if (yych == ' ') goto yy108;
goto yy106;
}
} else {
if (yych <= '/') {
if (yych <= '$') goto yy108;
if (yych <= '-') goto yy106;
if (yych <= '.') goto yy114;
goto yy108;
} else {
if (yych <= ':') {
if (yych <= '9') goto yy106;
goto yy108;
} else {
if (yych == '|') goto yy108;
goto yy106;
}
}
}
yy112:
yych = *++p;
if (yybm[0+yych] & 128) {
goto yy106;
}
if (yych <= '$') goto yy108;
if (yych <= '/') goto yy115;
goto yy108;
yy113:
yych = *++p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy108;
if (yych == '\n') goto yy108;
goto yy116;
} else {
if (yych <= '\r') goto yy108;
if (yych == ' ') goto yy108;
goto yy116;
}
} else {
if (yych <= '/') {
if (yych <= '$') goto yy108;
if (yych <= '-') goto yy116;
if (yych <= '.') goto yy117;
goto yy108;
} else {
if (yych <= ':') {
if (yych <= '9') goto yy116;
goto yy108;
} else {
if (yych == '|') goto yy108;
goto yy116;
}
}
}
yy114:
yych = *++p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy108;
if (yych == '\n') goto yy108;
goto yy106;
} else {
if (yych <= '\r') goto yy108;
if (yych == ' ') goto yy108;
goto yy106;
}
} else {
if (yych <= '/') {
if (yych <= '$') goto yy108;
if (yych <= '-') goto yy106;
if (yych <= '.') goto yy118;
goto yy108;
} else {
if (yych <= ':') {
if (yych <= '9') goto yy106;
goto yy108;
} else {
if (yych == '|') goto yy108;
goto yy106;
}
}
}
yy115:
yych = *++p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy108;
if (yych == '\n') goto yy108;
goto yy106;
} else {
if (yych <= '\r') goto yy108;
if (yych == ' ') goto yy108;
goto yy106;
}
} else {
if (yych <= '/') {
if (yych <= '$') goto yy108;
if (yych <= '-') goto yy106;
if (yych <= '.') goto yy119;
goto yy108;
} else {
if (yych <= ':') {
if (yych <= '9') goto yy106;
goto yy108;
} else {
if (yych == '|') goto yy108;
goto yy106;
}
}
}
yy116:
yych = *++p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy108;
if (yych == '\n') {
r = p;
goto yy120;
}
goto yy116;
} else {
if (yych <= '\r') {
r = p;
goto yy121;
}
if (yych == ' ') {
r = p;
goto yy120;
}
goto yy116;
}
} else {
if (yych <= '9') {
if (yych <= '$') goto yy108;
if (yych == '/') goto yy122;
goto yy116;
} else {
if (yych <= ':') {
r = p;
goto yy120;
}
if (yych == '|') {
r = p;
goto yy120;
}
goto yy116;
}
}
yy117:
yych = *++p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy108;
if (yych == '\n') goto yy108;
goto yy116;
} else {
if (yych <= '\r') goto yy108;
if (yych == ' ') goto yy108;
goto yy116;
}
} else {
if (yych <= '/') {
if (yych <= '$') goto yy108;
if (yych <= '-') goto yy116;
if (yych <= '.') goto yy123;
goto yy108;
} else {
if (yych <= ':') {
if (yych <= '9') goto yy116;
goto yy108;
} else {
if (yych == '|') goto yy108;
goto yy116;
}
}
}
yy118:
yych = *++p;
if (yybm[0+yych] & 128) {
goto yy106;
}
goto yy108;
yy119:
yych = *++p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy108;
if (yych == '\n') goto yy108;
goto yy106;
} else {
if (yych <= '\r') goto yy108;
if (yych == ' ') goto yy108;
goto yy106;
}
} else {
if (yych <= '/') {
if (yych <= '$') goto yy108;
if (yych <= '-') goto yy106;
if (yych <= '.') goto yy112;
goto yy108;
} else {
if (yych <= ':') {
if (yych <= '9') goto yy106;
goto yy108;
} else {
if (yych == '|') goto yy108;
goto yy106;
}
}
}
yy120:
++p;
p = r;
{ return finish(ofs_ + 2, p); }
yy121:
yych = *++p;
if (yych == '\n') goto yy120;
goto yy108;
yy122:
yych = *++p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy108;
if (yych == '\n') goto yy108;
goto yy116;
} else {
if (yych <= '\r') goto yy108;
if (yych == ' ') goto yy108;
goto yy116;
}
} else {
if (yych <= '/') {
if (yych <= '$') goto yy108;
if (yych <= '-') goto yy116;
if (yych <= '.') goto yy124;
goto yy108;
} else {
if (yych <= ':') {
if (yych <= '9') goto yy116;
goto yy108;
} else {
if (yych == '|') goto yy108;
goto yy116;
}
}
}
yy123:
yych = *++p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy108;
if (yych == '\n') goto yy108;
goto yy116;
} else {
if (yych <= '\r') goto yy108;
if (yych == ' ') goto yy108;
goto yy116;
}
} else {
if (yych <= '9') {
if (yych <= '$') goto yy108;
if (yych == '/') goto yy113;
goto yy116;
} else {
if (yych <= ':') goto yy108;
if (yych == '|') goto yy108;
goto yy116;
}
}
yy124:
yych = *++p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy108;
if (yych == '\n') goto yy108;
goto yy116;
} else {
if (yych <= '\r') goto yy108;
if (yych == ' ') goto yy108;
goto yy116;
}
} else {
if (yych <= '/') {
if (yych <= '$') goto yy108;
if (yych <= '-') goto yy116;
if (yych >= '/') goto yy108;
} else {
if (yych <= ':') {
if (yych <= '9') goto yy116;
goto yy108;
} else {
if (yych == '|') goto yy108;
goto yy116;
}
}
}
yych = *++p;
if (yych <= '#') {
if (yych <= '\f') {
if (yych <= 0x00) goto yy108;
if (yych == '\n') goto yy108;
goto yy116;
} else {
if (yych <= '\r') goto yy108;
if (yych == ' ') goto yy108;
goto yy116;
}
} else {
if (yych <= '9') {
if (yych <= '$') goto yy108;
if (yych == '/') goto yy108;
goto yy116;
} else {
if (yych <= ':') goto yy108;
if (yych == '|') goto yy108;
goto yy116;
}
}
}
} while (false);
return {};
}
bool Lexer::ReadPath(LexedPath* out, std::string* err) {
const char* p = ofs_;
const char* q;
const char* start;
for (;;) {
start = p;
{
unsigned char yych;
unsigned int yyaccept = 0;
static const unsigned char yybm[] = {
0, 32, 32, 32, 32, 32, 32, 32,
32, 32, 0, 32, 32, 0, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
64, 32, 32, 32, 0, 32, 32, 32,
32, 32, 32, 32, 32, 160, 160, 32,
160, 160, 160, 160, 160, 160, 160, 160,
160, 160, 0, 32, 32, 32, 32, 32,
32, 160, 160, 160, 160, 160, 160, 160,
160, 160, 160, 160, 160, 160, 160, 160,
160, 160, 160, 160, 160, 160, 160, 160,
160, 160, 160, 32, 32, 32, 32, 160,
32, 160, 160, 160, 160, 160, 160, 160,
160, 160, 160, 160, 160, 160, 160, 160,
160, 160, 160, 160, 160, 160, 160, 160,
160, 160, 160, 32, 0, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
};
yych = *p;
if (yybm[0+yych] & 32) {
goto yy127;
}
if (yych <= '\r') {
if (yych <= 0x00) goto yy126;
if (yych <= '\n') goto yy129;
goto yy130;
} else {
if (yych <= ' ') goto yy129;
if (yych <= '$') goto yy131;
goto yy129;
}
yy126:
++p;
{
last_token_ = start;
return UnexpectedNulError(start, err);
}
yy127:
yyaccept = 0;
yych = *(q = ++p);
if (yybm[0+yych] & 32) {
goto yy127;
}
if (yych <= ' ') goto yy128;
if (yych <= '$') goto yy132;
yy128:
{
continue;
}
yy129:
++p;
{
p = start;
break;
}
yy130:
yych = *++p;
if (yych == '\n') goto yy129;
{
last_token_ = start;
return Error(DescribeLastError(), err);
}
yy131:
yych = *++p;
if (yych <= '-') {
if (yych <= 0x1F) {
if (yych <= '\n') {
if (yych <= '\t') goto yy134;
goto yy136;
} else {
if (yych == '\r') goto yy137;
goto yy134;
}
} else {
if (yych <= '#') {
if (yych <= ' ') goto yy127;
goto yy134;
} else {
if (yych <= '$') goto yy127;
if (yych <= ',') goto yy134;
goto yy127;
}
}
} else {
if (yych <= '^') {
if (yych <= ':') {
if (yych <= '/') goto yy134;
goto yy127;
} else {
if (yych <= '@') goto yy134;
if (yych <= 'Z') goto yy127;
goto yy134;
}
} else {
if (yych <= '`') {
if (yych <= '_') goto yy127;
goto yy134;
} else {
if (yych <= 'z') goto yy127;
if (yych <= '{') goto yy138;
goto yy134;
}
}
}
yy132:
yych = *++p;
if (yych <= '-') {
if (yych <= 0x1F) {
if (yych <= '\n') {
if (yych >= '\n') goto yy136;
} else {
if (yych == '\r') goto yy139;
}
} else {
if (yych <= '#') {
if (yych <= ' ') goto yy127;
} else {
if (yych <= '$') goto yy127;
if (yych >= '-') goto yy127;
}
}
} else {
if (yych <= '^') {
if (yych <= ':') {
if (yych >= '0') goto yy127;
} else {
if (yych <= '@') goto yy133;
if (yych <= 'Z') goto yy127;
}
} else {
if (yych <= '`') {
if (yych <= '_') goto yy127;
} else {
if (yych <= 'z') goto yy127;
if (yych <= '{') goto yy140;
}
}
}
yy133:
p = q;
if (yyaccept == 0) {
goto yy128;
} else {
goto yy135;
}
yy134:
++p;
yy135:
{
last_token_ = start;
return Error("bad $-escape (literal $ must be written as $$)", err);
}
yy136:
yyaccept = 0;
yych = *(q = ++p);
if (yybm[0+yych] & 32) {
goto yy127;
}
if (yych <= '\r') goto yy128;
if (yych <= ' ') goto yy136;
if (yych <= '$') goto yy132;
goto yy128;
yy137:
yych = *++p;
if (yych == '\n') goto yy136;
goto yy135;
yy138:
yyaccept = 1;
yych = *(q = ++p);
if (yybm[0+yych] & 128) {
goto yy141;
}
goto yy135;
yy139:
yych = *++p;
if (yych == '\n') goto yy136;
goto yy133;
yy140:
yych = *++p;
if (yybm[0+yych] & 128) {
goto yy141;
}
goto yy133;
yy141:
yych = *++p;
if (yybm[0+yych] & 128) {
goto yy141;
}
if (yych == '}') goto yy127;
goto yy133;
}
}
*out = {};
out->str_ = StringPiece(ofs_, p - ofs_);
last_token_ = start;
ofs_ = p;
EatWhitespace();
return true;
}
/// Append the let binding's evaluated value to the output string. The input
/// StringPiece must include a valid binding terminator.
template <typename EvalVar>
static inline void EvaluateBinding(std::string* out_append, StringPiece value,
EvalVar&& eval_var) {
auto expand = [&eval_var](const char* start, const char* end) {
StringPiece var(start, end - start);
eval_var(var);
};
const char* p = value.data();
const char* q;
for (;;) {
const char* start = p;
{
unsigned char yych;
static const unsigned char yybm[] = {
0, 16, 16, 16, 16, 16, 16, 16,
16, 16, 0, 16, 16, 0, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
48, 16, 16, 16, 0, 16, 16, 16,
16, 16, 16, 16, 16, 208, 144, 16,
208, 208, 208, 208, 208, 208, 208, 208,
208, 208, 16, 16, 16, 16, 16, 16,
16, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 16, 16, 16, 16, 208,
16, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
};
yych = *p;
if (yybm[0+yych] & 16) {
goto yy145;
}
if (yych <= 0x00) goto yy143;
if (yych <= '\n') goto yy146;
if (yych <= '\r') goto yy147;
goto yy148;
yy143:
++p;
yy144:
{ assert(false && "bad input in EvaluateBinding"); abort(); }
yy145:
yych = *++p;
if (yybm[0+yych] & 16) {
goto yy145;
}
{ out_append->append(start, p - start); continue; }
yy146:
++p;
{ break; }
yy147:
yych = *++p;
if (yych == '\n') goto yy146;
goto yy144;
yy148:
yych = *(q = ++p);
if (yybm[0+yych] & 64) {
goto yy153;
}
if (yych <= ' ') {
if (yych <= '\f') {
if (yych != '\n') goto yy144;
} else {
if (yych <= '\r') goto yy150;
if (yych <= 0x1F) goto yy144;
goto yy152;
}
} else {
if (yych <= '/') {
if (yych == '$') goto yy152;
goto yy144;
} else {
if (yych <= ':') goto yy152;
if (yych <= '`') goto yy144;
if (yych <= '{') goto yy154;
goto yy144;
}
}
yy149:
yych = *++p;
if (yybm[0+yych] & 32) {
goto yy149;
}
{ continue; }
yy150:
yych = *++p;
if (yych == '\n') goto yy149;
yy151:
p = q;
goto yy144;
yy152:
++p;
{ out_append->push_back(start[1]); continue; }
yy153:
yych = *++p;
if (yybm[0+yych] & 64) {
goto yy153;
}
{ expand(start + 1, p); continue; }
yy154:
yych = *++p;
if (yych == '}') goto yy151;
goto yy156;
yy155:
yych = *++p;
yy156:
if (yybm[0+yych] & 128) {
goto yy155;
}
if (yych != '}') goto yy151;
++p;
{ expand(start + 2, p - 1); continue; }
}
}
assert((p == value.data() + value.size()) &&
"bad end pos in EvaluateBinding");
}
void EvaluateBindingInScope(std::string* out_append, StringPiece value,
ScopePosition pos) {
EvaluateBinding(out_append, value,
[out_append, &pos](const HashedStrView& var) {
Scope::EvaluateVariableAtPos(out_append, var, pos);
});
}
bool EvaluateBindingOnRule(std::string* out_append, StringPiece value,
EdgeEval* edge_eval, Scope* target, std::string* err) {
bool result = true;
EvaluateBinding(out_append, value,
[out_append, edge_eval, &result, target, err](const HashedStrView& var) {
result = result && edge_eval->EvaluateVariable(out_append, var, target, err);
});
return result;
}
std::string EvaluateBindingForTesting(StringPiece value) {
std::string result;
EvaluateBinding(&result, value, [&result](StringPiece var) {
result += "[$" + var.AsString() + "]";
});
return result;
}
/// Append an evaluated path to the output string.
///
/// This function does not canonicalize the output. Ninja canonicalizes paths for
/// build nodes, but not all paths (e.g. It doesn't canonicalize paths to
/// included ninja files.)
template <typename EvalVar>
static inline void EvaluatePath(std::string* out_append, const LexedPath& path,
EvalVar&& eval_var) {
auto expand = [&eval_var](const char* start, const char* end) {
StringPiece var(start, end - start);
eval_var(var);
};
const char* p = path.str_.data();
const char* q;
for (;;) {
const char* start = p;
{
unsigned char yych;
static const unsigned char yybm[] = {
0, 16, 16, 16, 16, 16, 16, 16,
16, 16, 0, 16, 16, 0, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
32, 16, 16, 16, 0, 16, 16, 16,
16, 16, 16, 16, 16, 208, 144, 16,
208, 208, 208, 208, 208, 208, 208, 208,
208, 208, 0, 16, 16, 16, 16, 16,
16, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 16, 16, 16, 16, 208,
16, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 208, 208, 208, 208, 208,
208, 208, 208, 16, 0, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
};
yych = *p;
if (yybm[0+yych] & 16) {
goto yy160;
}
if (yych <= '\r') {
if (yych <= 0x00) goto yy158;
if (yych <= '\n') goto yy161;
goto yy162;
} else {
if (yych <= ' ') goto yy161;
if (yych <= '$') goto yy163;
goto yy161;
}
yy158:
++p;
yy159:
{ assert(false && "bad input in EvaluatePath"); abort(); }
yy160:
yych = *++p;
if (yybm[0+yych] & 16) {
goto yy160;
}
{ out_append->append(start, p - start); continue; }
yy161:
++p;
{ p = start; break; }
yy162:
yych = *++p;
if (yych == '\n') goto yy161;
goto yy159;
yy163:
yych = *(q = ++p);
if (yybm[0+yych] & 64) {
goto yy168;
}
if (yych <= ' ') {
if (yych <= '\f') {
if (yych != '\n') goto yy159;
} else {
if (yych <= '\r') goto yy165;
if (yych <= 0x1F) goto yy159;
goto yy167;
}
} else {
if (yych <= '/') {
if (yych == '$') goto yy167;
goto yy159;
} else {
if (yych <= ':') goto yy167;
if (yych <= '`') goto yy159;
if (yych <= '{') goto yy169;
goto yy159;
}
}
yy164:
yych = *++p;
if (yybm[0+yych] & 32) {
goto yy164;
}
{ continue; }
yy165:
yych = *++p;
if (yych == '\n') goto yy164;
yy166:
p = q;
goto yy159;
yy167:
++p;
{ out_append->push_back(start[1]); continue; }
yy168:
yych = *++p;
if (yybm[0+yych] & 64) {
goto yy168;
}
{ expand(start + 1, p); continue; }
yy169:
yych = *++p;
if (yych == '}') goto yy166;
goto yy171;
yy170:
yych = *++p;
yy171:
if (yybm[0+yych] & 128) {
goto yy170;
}
if (yych != '}') goto yy166;
++p;
{ expand(start + 2, p - 1); continue; }
}
}
assert((p == path.str_.data() + path.str_.size()) &&
"bad end pos in EvaluatePath");
}
void EvaluatePathInScope(std::string* out_append, const LexedPath& path,
ScopePosition pos) {
EvaluatePath(out_append, path, [out_append, &pos](const HashedStrView& var) {
Scope::EvaluateVariableAtPos(out_append, var, pos);
});
}
void EvaluatePathOnEdge(std::string* out_append, const LexedPath& path,
const Edge& edge) {
EvaluatePath(out_append, path, [out_append, &edge](const HashedStrView& var) {
// First look for a binding on the edge itself, then fall back to the
// edge's enclosing scope.
if (edge.EvaluateVariableSelfOnly(out_append, var))
return;
Scope::EvaluateVariableAtPos(out_append, var, edge.pos_.scope_pos());
});
}
std::string EvaluatePathForTesting(const LexedPath& path) {
std::string result;
EvaluatePath(&result, path, [&result](StringPiece var) {
result += "[$" + var.AsString() + "]";
});
return result;
}