| /* 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 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 yy9; |
| } |
| if (yych <= '^') { |
| if (yych <= ',') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy2; |
| if (yych == '\n') goto yy6; |
| goto yy4; |
| } else { |
| if (yych <= '\r') goto yy8; |
| if (yych == '#') goto yy12; |
| goto yy4; |
| } |
| } else { |
| if (yych <= ':') { |
| if (yych == '/') goto yy4; |
| if (yych <= '9') goto yy13; |
| goto yy16; |
| } else { |
| if (yych <= '=') { |
| if (yych <= '<') goto yy4; |
| goto yy18; |
| } else { |
| if (yych <= '@') goto yy4; |
| if (yych <= 'Z') goto yy13; |
| goto yy4; |
| } |
| } |
| } |
| } else { |
| if (yych <= 'i') { |
| if (yych <= 'b') { |
| if (yych == '`') goto yy4; |
| if (yych <= 'a') goto yy13; |
| goto yy20; |
| } else { |
| if (yych == 'd') goto yy21; |
| if (yych <= 'h') goto yy13; |
| goto yy22; |
| } |
| } else { |
| if (yych <= 'r') { |
| if (yych == 'p') goto yy23; |
| if (yych <= 'q') goto yy13; |
| goto yy24; |
| } else { |
| if (yych <= 'z') { |
| if (yych <= 's') goto yy25; |
| goto yy13; |
| } else { |
| if (yych == '|') goto yy26; |
| goto yy4; |
| } |
| } |
| } |
| } |
| yy2: |
| ++p; |
| { token = (start == EndOfFile()) ? TEOF : TNUL; break; } |
| yy4: |
| ++p; |
| yy5: |
| { token = ERROR; break; } |
| yy6: |
| ++p; |
| { token = NEWLINE; break; } |
| yy8: |
| yych = *++p; |
| if (yych == '\n') goto yy6; |
| goto yy5; |
| yy9: |
| yyaccept = 0; |
| yych = *(q = ++p); |
| if (yybm[0+yych] & 32) { |
| goto yy9; |
| } |
| if (yych <= '\f') { |
| if (yych == '\n') goto yy6; |
| } else { |
| if (yych <= '\r') goto yy28; |
| if (yych == '#') goto yy30; |
| } |
| yy11: |
| { token = INDENT; break; } |
| yy12: |
| yyaccept = 1; |
| yych = *(q = ++p); |
| if (yych <= 0x00) goto yy5; |
| goto yy31; |
| yy13: |
| yych = *++p; |
| yy14: |
| if (yybm[0+yych] & 64) { |
| goto yy13; |
| } |
| { token = IDENT; break; } |
| yy16: |
| ++p; |
| { token = COLON; break; } |
| yy18: |
| ++p; |
| { token = EQUALS; break; } |
| yy20: |
| yych = *++p; |
| if (yych == 'u') goto yy35; |
| goto yy14; |
| yy21: |
| yych = *++p; |
| if (yych == 'e') goto yy36; |
| goto yy14; |
| yy22: |
| yych = *++p; |
| if (yych == 'n') goto yy37; |
| goto yy14; |
| yy23: |
| yych = *++p; |
| if (yych == 'o') goto yy38; |
| goto yy14; |
| yy24: |
| yych = *++p; |
| if (yych == 'u') goto yy39; |
| goto yy14; |
| yy25: |
| yych = *++p; |
| if (yych == 'u') goto yy40; |
| goto yy14; |
| yy26: |
| yych = *++p; |
| if (yych == '@') goto yy41; |
| if (yych == '|') goto yy43; |
| { token = PIPE; break; } |
| yy28: |
| yych = *++p; |
| if (yych == '\n') goto yy6; |
| yy29: |
| p = q; |
| if (yyaccept == 0) { |
| goto yy11; |
| } else { |
| goto yy5; |
| } |
| yy30: |
| yych = *++p; |
| yy31: |
| if (yybm[0+yych] & 128) { |
| goto yy30; |
| } |
| if (yych <= 0x00) goto yy29; |
| if (yych >= '\v') { |
| r = p; |
| goto yy34; |
| } |
| r = p; |
| yy32: |
| ++p; |
| p = r; |
| { continue; } |
| yy34: |
| yych = *++p; |
| if (yych == '\n') goto yy32; |
| goto yy29; |
| yy35: |
| yych = *++p; |
| if (yych == 'i') goto yy45; |
| goto yy14; |
| yy36: |
| yych = *++p; |
| if (yych == 'f') goto yy46; |
| goto yy14; |
| yy37: |
| yych = *++p; |
| if (yych == 'c') goto yy47; |
| goto yy14; |
| yy38: |
| yych = *++p; |
| if (yych == 'o') goto yy48; |
| goto yy14; |
| yy39: |
| yych = *++p; |
| if (yych == 'l') goto yy49; |
| goto yy14; |
| yy40: |
| yych = *++p; |
| if (yych == 'b') goto yy50; |
| goto yy14; |
| yy41: |
| ++p; |
| { token = PIPEAT; break; } |
| yy43: |
| ++p; |
| { token = PIPE2; break; } |
| yy45: |
| yych = *++p; |
| if (yych == 'l') goto yy51; |
| goto yy14; |
| yy46: |
| yych = *++p; |
| if (yych == 'a') goto yy52; |
| goto yy14; |
| yy47: |
| yych = *++p; |
| if (yych == 'l') goto yy53; |
| goto yy14; |
| yy48: |
| yych = *++p; |
| if (yych == 'l') goto yy54; |
| goto yy14; |
| yy49: |
| yych = *++p; |
| if (yych == 'e') goto yy56; |
| goto yy14; |
| yy50: |
| yych = *++p; |
| if (yych == 'n') goto yy58; |
| goto yy14; |
| yy51: |
| yych = *++p; |
| if (yych == 'd') goto yy59; |
| goto yy14; |
| yy52: |
| yych = *++p; |
| if (yych == 'u') goto yy61; |
| goto yy14; |
| yy53: |
| yych = *++p; |
| if (yych == 'u') goto yy62; |
| goto yy14; |
| yy54: |
| yych = *++p; |
| if (yybm[0+yych] & 64) { |
| goto yy13; |
| } |
| { token = POOL; break; } |
| yy56: |
| yych = *++p; |
| if (yybm[0+yych] & 64) { |
| goto yy13; |
| } |
| { token = RULE; break; } |
| yy58: |
| yych = *++p; |
| if (yych == 'i') goto yy63; |
| goto yy14; |
| yy59: |
| yych = *++p; |
| if (yybm[0+yych] & 64) { |
| goto yy13; |
| } |
| { token = BUILD; break; } |
| yy61: |
| yych = *++p; |
| if (yych == 'l') goto yy64; |
| goto yy14; |
| yy62: |
| yych = *++p; |
| if (yych == 'd') goto yy65; |
| goto yy14; |
| yy63: |
| yych = *++p; |
| if (yych == 'n') goto yy66; |
| goto yy14; |
| yy64: |
| yych = *++p; |
| if (yych == 't') goto yy67; |
| goto yy14; |
| yy65: |
| yych = *++p; |
| if (yych == 'e') goto yy69; |
| goto yy14; |
| yy66: |
| yych = *++p; |
| if (yych == 'j') goto yy71; |
| goto yy14; |
| yy67: |
| yych = *++p; |
| if (yybm[0+yych] & 64) { |
| goto yy13; |
| } |
| { token = DEFAULT; break; } |
| yy69: |
| yych = *++p; |
| if (yybm[0+yych] & 64) { |
| goto yy13; |
| } |
| { token = INCLUDE; break; } |
| yy71: |
| yych = *++p; |
| if (yych != 'a') goto yy14; |
| yych = *++p; |
| if (yybm[0+yych] & 64) { |
| goto yy13; |
| } |
| { 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 yy81; |
| } |
| if (yych <= '\f') { |
| if (yych == '\n') goto yy78; |
| } else { |
| if (yych <= '\r') goto yy80; |
| if (yych == '#') goto yy84; |
| } |
| ++p; |
| yy77: |
| { last_token_ = ofs_ = start; return false; } |
| yy78: |
| ++p; |
| { last_token_ = ofs_ = start; return false; } |
| yy80: |
| yych = *++p; |
| if (yych == '\n') goto yy78; |
| goto yy77; |
| yy81: |
| yyaccept = 0; |
| yych = *(q = ++p); |
| if (yybm[0+yych] & 64) { |
| goto yy81; |
| } |
| if (yych <= '\f') { |
| if (yych == '\n') goto yy78; |
| } else { |
| if (yych <= '\r') goto yy85; |
| if (yych == '#') goto yy87; |
| } |
| yy83: |
| { last_token_ = start; ofs_ = p; return true; } |
| yy84: |
| yyaccept = 1; |
| yych = *(q = ++p); |
| if (yych <= 0x00) goto yy77; |
| goto yy88; |
| yy85: |
| yych = *++p; |
| if (yych == '\n') goto yy78; |
| yy86: |
| p = q; |
| if (yyaccept == 0) { |
| goto yy83; |
| } else { |
| goto yy77; |
| } |
| yy87: |
| yych = *++p; |
| yy88: |
| if (yybm[0+yych] & 128) { |
| goto yy87; |
| } |
| if (yych <= 0x00) goto yy86; |
| if (yych >= '\v') goto yy91; |
| yy89: |
| ++p; |
| { continue; } |
| yy91: |
| yych = *++p; |
| if (yych == '\n') goto yy89; |
| goto yy86; |
| } |
| |
| } |
| } |
| |
| 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 yy98; |
| } |
| if (yych <= 0x00) goto yy94; |
| if (yych == '$') goto yy101; |
| goto yy96; |
| yy94: |
| ++p; |
| { break; } |
| yy96: |
| ++p; |
| yy97: |
| { break; } |
| yy98: |
| yych = *++p; |
| if (yybm[0+yych] & 128) { |
| goto yy98; |
| } |
| { continue; } |
| yy101: |
| yych = *(q = ++p); |
| if (yych == '\n') goto yy102; |
| if (yych == '\r') goto yy104; |
| goto yy97; |
| yy102: |
| ++p; |
| { continue; } |
| yy104: |
| yych = *++p; |
| if (yych == '\n') goto yy102; |
| p = q; |
| goto yy97; |
| } |
| |
| } |
| } |
| |
| 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 yy110; |
| } |
| ++p; |
| { |
| last_token_ = start; |
| return false; |
| } |
| yy110: |
| yych = *++p; |
| if (yybm[0+yych] & 128) { |
| goto yy110; |
| } |
| { |
| *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 yy117; |
| } |
| if (yych <= 0x00) goto yy115; |
| if (yych <= '\n') goto yy120; |
| if (yych <= '\r') goto yy122; |
| goto yy124; |
| yy115: |
| ++p; |
| { |
| last_token_ = start; |
| return UnexpectedNulError(start, err); |
| } |
| yy117: |
| yyaccept = 0; |
| yych = *(q = ++p); |
| if (yybm[0+yych] & 64) { |
| goto yy117; |
| } |
| if (yych >= 0x0E) goto yy125; |
| yy119: |
| { |
| continue; |
| } |
| yy120: |
| ++p; |
| { |
| break; |
| } |
| yy122: |
| yych = *++p; |
| if (yych == '\n') goto yy120; |
| { |
| last_token_ = start; |
| return Error(DescribeLastError(), err); |
| } |
| yy124: |
| yych = *++p; |
| if (yych <= '-') { |
| if (yych <= 0x1F) { |
| if (yych <= '\n') { |
| if (yych <= '\t') goto yy127; |
| goto yy117; |
| } else { |
| if (yych == '\r') goto yy129; |
| goto yy127; |
| } |
| } else { |
| if (yych <= '#') { |
| if (yych <= ' ') goto yy117; |
| goto yy127; |
| } else { |
| if (yych <= '$') goto yy117; |
| if (yych <= ',') goto yy127; |
| goto yy117; |
| } |
| } |
| } else { |
| if (yych <= '^') { |
| if (yych <= ':') { |
| if (yych <= '/') goto yy127; |
| goto yy117; |
| } else { |
| if (yych <= '@') goto yy127; |
| if (yych <= 'Z') goto yy117; |
| goto yy127; |
| } |
| } else { |
| if (yych <= '`') { |
| if (yych <= '_') goto yy117; |
| goto yy127; |
| } else { |
| if (yych <= 'z') goto yy117; |
| if (yych <= '{') goto yy130; |
| goto yy127; |
| } |
| } |
| } |
| yy125: |
| yych = *++p; |
| if (yych <= '-') { |
| if (yych <= 0x1F) { |
| if (yych <= '\n') { |
| if (yych >= '\n') goto yy117; |
| } else { |
| if (yych == '\r') goto yy131; |
| } |
| } else { |
| if (yych <= '#') { |
| if (yych <= ' ') goto yy117; |
| } else { |
| if (yych <= '$') goto yy117; |
| if (yych >= '-') goto yy117; |
| } |
| } |
| } else { |
| if (yych <= '^') { |
| if (yych <= ':') { |
| if (yych >= '0') goto yy117; |
| } else { |
| if (yych <= '@') goto yy126; |
| if (yych <= 'Z') goto yy117; |
| } |
| } else { |
| if (yych <= '`') { |
| if (yych <= '_') goto yy117; |
| } else { |
| if (yych <= 'z') goto yy117; |
| if (yych <= '{') goto yy132; |
| } |
| } |
| } |
| yy126: |
| p = q; |
| if (yyaccept == 0) { |
| goto yy119; |
| } else { |
| goto yy128; |
| } |
| yy127: |
| ++p; |
| yy128: |
| { |
| last_token_ = start; |
| return Error("bad $-escape (literal $ must be written as $$)", err); |
| } |
| yy129: |
| yych = *++p; |
| if (yych == '\n') goto yy117; |
| goto yy128; |
| yy130: |
| yyaccept = 1; |
| yych = *(q = ++p); |
| if (yybm[0+yych] & 128) { |
| goto yy133; |
| } |
| goto yy128; |
| yy131: |
| yych = *++p; |
| if (yych == '\n') goto yy117; |
| goto yy126; |
| yy132: |
| yych = *++p; |
| if (yybm[0+yych] & 128) { |
| goto yy133; |
| } |
| goto yy126; |
| yy133: |
| yych = *++p; |
| if (yybm[0+yych] & 128) { |
| goto yy133; |
| } |
| if (yych == '}') goto yy117; |
| goto yy126; |
| } |
| |
| } |
| *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 yy137; |
| if (yych != '\n') goto yy139; |
| } else { |
| if (yych <= '\r') goto yy137; |
| if (yych != ' ') goto yy139; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych <= '$') goto yy137; |
| if (yych <= '-') goto yy139; |
| if (yych <= '.') goto yy140; |
| goto yy141; |
| } else { |
| if (yych <= ':') { |
| if (yych <= '9') goto yy139; |
| } else { |
| if (yych != '|') goto yy139; |
| } |
| } |
| } |
| yy137: |
| ++p; |
| yy138: |
| { break; } |
| yy139: |
| yych = *(q = ++p); |
| if (yych <= 0x00) goto yy138; |
| if (yych == '$') goto yy138; |
| goto yy143; |
| yy140: |
| yych = *(q = ++p); |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy138; |
| if (yych == '\n') goto yy138; |
| goto yy142; |
| } else { |
| if (yych <= '\r') goto yy138; |
| if (yych == ' ') goto yy138; |
| goto yy142; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych <= '$') goto yy138; |
| if (yych <= '-') goto yy142; |
| if (yych <= '.') goto yy149; |
| goto yy150; |
| } else { |
| if (yych <= ':') { |
| if (yych <= '9') goto yy142; |
| goto yy138; |
| } else { |
| if (yych == '|') goto yy138; |
| goto yy142; |
| } |
| } |
| } |
| yy141: |
| yych = *(q = ++p); |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy138; |
| if (yych == '\n') goto yy138; |
| } else { |
| if (yych <= '\r') goto yy138; |
| if (yych == ' ') goto yy138; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych <= '$') goto yy138; |
| if (yych <= '-') goto yy142; |
| if (yych <= '.') goto yy151; |
| goto yy138; |
| } else { |
| if (yych <= ':') { |
| if (yych >= ':') goto yy138; |
| } else { |
| if (yych == '|') goto yy138; |
| } |
| } |
| } |
| yy142: |
| yych = *++p; |
| yy143: |
| if (yybm[0+yych] & 128) { |
| goto yy142; |
| } |
| if (yych <= '\r') { |
| if (yych <= 0x00) goto yy144; |
| if (yych <= '\n') { |
| r = p; |
| goto yy145; |
| } |
| r = p; |
| goto yy147; |
| } else { |
| if (yych <= ' ') { |
| r = p; |
| goto yy145; |
| } |
| if (yych <= '$') goto yy144; |
| if (yych <= '/') goto yy148; |
| r = p; |
| goto yy145; |
| } |
| yy144: |
| p = q; |
| goto yy138; |
| yy145: |
| ++p; |
| p = r; |
| { return finish(ofs_, p); } |
| yy147: |
| yych = *++p; |
| if (yych == '\n') goto yy145; |
| goto yy144; |
| yy148: |
| yych = *++p; |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy144; |
| if (yych == '\n') goto yy144; |
| goto yy142; |
| } else { |
| if (yych <= '\r') goto yy144; |
| if (yych == ' ') goto yy144; |
| goto yy142; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych <= '$') goto yy144; |
| if (yych <= '-') goto yy142; |
| if (yych <= '.') goto yy151; |
| goto yy144; |
| } else { |
| if (yych <= ':') { |
| if (yych <= '9') goto yy142; |
| goto yy144; |
| } else { |
| if (yych == '|') goto yy144; |
| goto yy142; |
| } |
| } |
| } |
| yy149: |
| yych = *++p; |
| if (yybm[0+yych] & 128) { |
| goto yy142; |
| } |
| if (yych <= '$') goto yy144; |
| if (yych <= '/') goto yy152; |
| goto yy144; |
| yy150: |
| yych = *++p; |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy144; |
| if (yych == '\n') goto yy144; |
| goto yy153; |
| } else { |
| if (yych <= '\r') goto yy144; |
| if (yych == ' ') goto yy144; |
| goto yy153; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych <= '$') goto yy144; |
| if (yych <= '-') goto yy153; |
| if (yych <= '.') goto yy155; |
| goto yy144; |
| } else { |
| if (yych <= ':') { |
| if (yych <= '9') goto yy153; |
| goto yy144; |
| } else { |
| if (yych == '|') goto yy144; |
| goto yy153; |
| } |
| } |
| } |
| yy151: |
| yych = *++p; |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy144; |
| if (yych == '\n') goto yy144; |
| goto yy142; |
| } else { |
| if (yych <= '\r') goto yy144; |
| if (yych == ' ') goto yy144; |
| goto yy142; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych <= '$') goto yy144; |
| if (yych <= '-') goto yy142; |
| if (yych <= '.') goto yy156; |
| goto yy144; |
| } else { |
| if (yych <= ':') { |
| if (yych <= '9') goto yy142; |
| goto yy144; |
| } else { |
| if (yych == '|') goto yy144; |
| goto yy142; |
| } |
| } |
| } |
| yy152: |
| yych = *++p; |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy144; |
| if (yych == '\n') goto yy144; |
| goto yy142; |
| } else { |
| if (yych <= '\r') goto yy144; |
| if (yych == ' ') goto yy144; |
| goto yy142; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych <= '$') goto yy144; |
| if (yych <= '-') goto yy142; |
| if (yych <= '.') goto yy157; |
| goto yy144; |
| } else { |
| if (yych <= ':') { |
| if (yych <= '9') goto yy142; |
| goto yy144; |
| } else { |
| if (yych == '|') goto yy144; |
| goto yy142; |
| } |
| } |
| } |
| yy153: |
| yych = *++p; |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy144; |
| if (yych == '\n') { |
| r = p; |
| goto yy158; |
| } |
| goto yy153; |
| } else { |
| if (yych <= '\r') { |
| r = p; |
| goto yy160; |
| } |
| if (yych == ' ') { |
| r = p; |
| goto yy158; |
| } |
| goto yy153; |
| } |
| } else { |
| if (yych <= '9') { |
| if (yych <= '$') goto yy144; |
| if (yych == '/') goto yy161; |
| goto yy153; |
| } else { |
| if (yych <= ':') { |
| r = p; |
| goto yy158; |
| } |
| if (yych == '|') { |
| r = p; |
| goto yy158; |
| } |
| goto yy153; |
| } |
| } |
| yy155: |
| yych = *++p; |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy144; |
| if (yych == '\n') goto yy144; |
| goto yy153; |
| } else { |
| if (yych <= '\r') goto yy144; |
| if (yych == ' ') goto yy144; |
| goto yy153; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych <= '$') goto yy144; |
| if (yych <= '-') goto yy153; |
| if (yych <= '.') goto yy162; |
| goto yy144; |
| } else { |
| if (yych <= ':') { |
| if (yych <= '9') goto yy153; |
| goto yy144; |
| } else { |
| if (yych == '|') goto yy144; |
| goto yy153; |
| } |
| } |
| } |
| yy156: |
| yych = *++p; |
| if (yybm[0+yych] & 128) { |
| goto yy142; |
| } |
| goto yy144; |
| yy157: |
| yych = *++p; |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy144; |
| if (yych == '\n') goto yy144; |
| goto yy142; |
| } else { |
| if (yych <= '\r') goto yy144; |
| if (yych == ' ') goto yy144; |
| goto yy142; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych <= '$') goto yy144; |
| if (yych <= '-') goto yy142; |
| if (yych <= '.') goto yy149; |
| goto yy144; |
| } else { |
| if (yych <= ':') { |
| if (yych <= '9') goto yy142; |
| goto yy144; |
| } else { |
| if (yych == '|') goto yy144; |
| goto yy142; |
| } |
| } |
| } |
| yy158: |
| ++p; |
| p = r; |
| { return finish(ofs_ + 2, p); } |
| yy160: |
| yych = *++p; |
| if (yych == '\n') goto yy158; |
| goto yy144; |
| yy161: |
| yych = *++p; |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy144; |
| if (yych == '\n') goto yy144; |
| goto yy153; |
| } else { |
| if (yych <= '\r') goto yy144; |
| if (yych == ' ') goto yy144; |
| goto yy153; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych <= '$') goto yy144; |
| if (yych <= '-') goto yy153; |
| if (yych <= '.') goto yy163; |
| goto yy144; |
| } else { |
| if (yych <= ':') { |
| if (yych <= '9') goto yy153; |
| goto yy144; |
| } else { |
| if (yych == '|') goto yy144; |
| goto yy153; |
| } |
| } |
| } |
| yy162: |
| yych = *++p; |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy144; |
| if (yych == '\n') goto yy144; |
| goto yy153; |
| } else { |
| if (yych <= '\r') goto yy144; |
| if (yych == ' ') goto yy144; |
| goto yy153; |
| } |
| } else { |
| if (yych <= '9') { |
| if (yych <= '$') goto yy144; |
| if (yych == '/') goto yy150; |
| goto yy153; |
| } else { |
| if (yych <= ':') goto yy144; |
| if (yych == '|') goto yy144; |
| goto yy153; |
| } |
| } |
| yy163: |
| yych = *++p; |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy144; |
| if (yych == '\n') goto yy144; |
| goto yy153; |
| } else { |
| if (yych <= '\r') goto yy144; |
| if (yych == ' ') goto yy144; |
| goto yy153; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych <= '$') goto yy144; |
| if (yych <= '-') goto yy153; |
| if (yych >= '/') goto yy144; |
| } else { |
| if (yych <= ':') { |
| if (yych <= '9') goto yy153; |
| goto yy144; |
| } else { |
| if (yych == '|') goto yy144; |
| goto yy153; |
| } |
| } |
| } |
| yych = *++p; |
| if (yych <= '#') { |
| if (yych <= '\f') { |
| if (yych <= 0x00) goto yy144; |
| if (yych == '\n') goto yy144; |
| goto yy153; |
| } else { |
| if (yych <= '\r') goto yy144; |
| if (yych == ' ') goto yy144; |
| goto yy153; |
| } |
| } else { |
| if (yych <= '9') { |
| if (yych <= '$') goto yy144; |
| if (yych == '/') goto yy144; |
| goto yy153; |
| } else { |
| if (yych <= ':') goto yy144; |
| if (yych == '|') goto yy144; |
| goto yy153; |
| } |
| } |
| } |
| |
| } 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 yy169; |
| } |
| if (yych <= '\r') { |
| if (yych <= 0x00) goto yy167; |
| if (yych <= '\n') goto yy172; |
| goto yy174; |
| } else { |
| if (yych <= ' ') goto yy172; |
| if (yych <= '$') goto yy176; |
| goto yy172; |
| } |
| yy167: |
| ++p; |
| { |
| last_token_ = start; |
| return UnexpectedNulError(start, err); |
| } |
| yy169: |
| yyaccept = 0; |
| yych = *(q = ++p); |
| if (yybm[0+yych] & 32) { |
| goto yy169; |
| } |
| if (yych <= ' ') goto yy171; |
| if (yych <= '$') goto yy177; |
| yy171: |
| { |
| continue; |
| } |
| yy172: |
| ++p; |
| { |
| p = start; |
| break; |
| } |
| yy174: |
| yych = *++p; |
| if (yych == '\n') goto yy172; |
| { |
| last_token_ = start; |
| return Error(DescribeLastError(), err); |
| } |
| yy176: |
| yych = *++p; |
| if (yych <= '-') { |
| if (yych <= 0x1F) { |
| if (yych <= '\n') { |
| if (yych <= '\t') goto yy179; |
| goto yy181; |
| } else { |
| if (yych == '\r') goto yy183; |
| goto yy179; |
| } |
| } else { |
| if (yych <= '#') { |
| if (yych <= ' ') goto yy169; |
| goto yy179; |
| } else { |
| if (yych <= '$') goto yy169; |
| if (yych <= ',') goto yy179; |
| goto yy169; |
| } |
| } |
| } else { |
| if (yych <= '^') { |
| if (yych <= ':') { |
| if (yych <= '/') goto yy179; |
| goto yy169; |
| } else { |
| if (yych <= '@') goto yy179; |
| if (yych <= 'Z') goto yy169; |
| goto yy179; |
| } |
| } else { |
| if (yych <= '`') { |
| if (yych <= '_') goto yy169; |
| goto yy179; |
| } else { |
| if (yych <= 'z') goto yy169; |
| if (yych <= '{') goto yy184; |
| goto yy179; |
| } |
| } |
| } |
| yy177: |
| yych = *++p; |
| if (yych <= '-') { |
| if (yych <= 0x1F) { |
| if (yych <= '\n') { |
| if (yych >= '\n') goto yy181; |
| } else { |
| if (yych == '\r') goto yy185; |
| } |
| } else { |
| if (yych <= '#') { |
| if (yych <= ' ') goto yy169; |
| } else { |
| if (yych <= '$') goto yy169; |
| if (yych >= '-') goto yy169; |
| } |
| } |
| } else { |
| if (yych <= '^') { |
| if (yych <= ':') { |
| if (yych >= '0') goto yy169; |
| } else { |
| if (yych <= '@') goto yy178; |
| if (yych <= 'Z') goto yy169; |
| } |
| } else { |
| if (yych <= '`') { |
| if (yych <= '_') goto yy169; |
| } else { |
| if (yych <= 'z') goto yy169; |
| if (yych <= '{') goto yy186; |
| } |
| } |
| } |
| yy178: |
| p = q; |
| if (yyaccept == 0) { |
| goto yy171; |
| } else { |
| goto yy180; |
| } |
| yy179: |
| ++p; |
| yy180: |
| { |
| last_token_ = start; |
| return Error("bad $-escape (literal $ must be written as $$)", err); |
| } |
| yy181: |
| yyaccept = 0; |
| yych = *(q = ++p); |
| if (yybm[0+yych] & 32) { |
| goto yy169; |
| } |
| if (yych <= '\r') goto yy171; |
| if (yych <= ' ') goto yy181; |
| if (yych <= '$') goto yy177; |
| goto yy171; |
| yy183: |
| yych = *++p; |
| if (yych == '\n') goto yy181; |
| goto yy180; |
| yy184: |
| yyaccept = 1; |
| yych = *(q = ++p); |
| if (yybm[0+yych] & 128) { |
| goto yy187; |
| } |
| goto yy180; |
| yy185: |
| yych = *++p; |
| if (yych == '\n') goto yy181; |
| goto yy178; |
| yy186: |
| yych = *++p; |
| if (yybm[0+yych] & 128) { |
| goto yy187; |
| } |
| goto yy178; |
| yy187: |
| yych = *++p; |
| if (yybm[0+yych] & 128) { |
| goto yy187; |
| } |
| if (yych == '}') goto yy169; |
| goto yy178; |
| } |
| |
| } |
| *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 yy193; |
| } |
| if (yych <= 0x00) goto yy191; |
| if (yych <= '\n') goto yy196; |
| if (yych <= '\r') goto yy198; |
| goto yy199; |
| yy191: |
| ++p; |
| yy192: |
| { assert(false && "bad input in EvaluateBinding"); abort(); } |
| yy193: |
| yych = *++p; |
| if (yybm[0+yych] & 16) { |
| goto yy193; |
| } |
| { out_append->append(start, p - start); continue; } |
| yy196: |
| ++p; |
| { break; } |
| yy198: |
| yych = *++p; |
| if (yych == '\n') goto yy196; |
| goto yy192; |
| yy199: |
| yych = *(q = ++p); |
| if (yybm[0+yych] & 64) { |
| goto yy207; |
| } |
| if (yych <= ' ') { |
| if (yych <= '\f') { |
| if (yych != '\n') goto yy192; |
| } else { |
| if (yych <= '\r') goto yy203; |
| if (yych <= 0x1F) goto yy192; |
| goto yy205; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych == '$') goto yy205; |
| goto yy192; |
| } else { |
| if (yych <= ':') goto yy205; |
| if (yych <= '`') goto yy192; |
| if (yych <= '{') goto yy210; |
| goto yy192; |
| } |
| } |
| yy200: |
| yych = *++p; |
| if (yybm[0+yych] & 32) { |
| goto yy200; |
| } |
| { continue; } |
| yy203: |
| yych = *++p; |
| if (yych == '\n') goto yy200; |
| yy204: |
| p = q; |
| goto yy192; |
| yy205: |
| ++p; |
| { out_append->push_back(start[1]); continue; } |
| yy207: |
| yych = *++p; |
| if (yybm[0+yych] & 64) { |
| goto yy207; |
| } |
| { expand(start + 1, p); continue; } |
| yy210: |
| yych = *++p; |
| if (yych == '}') goto yy204; |
| goto yy212; |
| yy211: |
| yych = *++p; |
| yy212: |
| if (yybm[0+yych] & 128) { |
| goto yy211; |
| } |
| if (yych != '}') goto yy204; |
| ++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, std::string* err) { |
| bool result = true; |
| EvaluateBinding(out_append, value, |
| [out_append, edge_eval, &result, err](const HashedStrView& var) { |
| result = result && edge_eval->EvaluateVariable(out_append, var, 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 yy219; |
| } |
| if (yych <= '\r') { |
| if (yych <= 0x00) goto yy217; |
| if (yych <= '\n') goto yy222; |
| goto yy224; |
| } else { |
| if (yych <= ' ') goto yy222; |
| if (yych <= '$') goto yy225; |
| goto yy222; |
| } |
| yy217: |
| ++p; |
| yy218: |
| { assert(false && "bad input in EvaluatePath"); abort(); } |
| yy219: |
| yych = *++p; |
| if (yybm[0+yych] & 16) { |
| goto yy219; |
| } |
| { out_append->append(start, p - start); continue; } |
| yy222: |
| ++p; |
| { p = start; break; } |
| yy224: |
| yych = *++p; |
| if (yych == '\n') goto yy222; |
| goto yy218; |
| yy225: |
| yych = *(q = ++p); |
| if (yybm[0+yych] & 64) { |
| goto yy233; |
| } |
| if (yych <= ' ') { |
| if (yych <= '\f') { |
| if (yych != '\n') goto yy218; |
| } else { |
| if (yych <= '\r') goto yy229; |
| if (yych <= 0x1F) goto yy218; |
| goto yy231; |
| } |
| } else { |
| if (yych <= '/') { |
| if (yych == '$') goto yy231; |
| goto yy218; |
| } else { |
| if (yych <= ':') goto yy231; |
| if (yych <= '`') goto yy218; |
| if (yych <= '{') goto yy236; |
| goto yy218; |
| } |
| } |
| yy226: |
| yych = *++p; |
| if (yybm[0+yych] & 32) { |
| goto yy226; |
| } |
| { continue; } |
| yy229: |
| yych = *++p; |
| if (yych == '\n') goto yy226; |
| yy230: |
| p = q; |
| goto yy218; |
| yy231: |
| ++p; |
| { out_append->push_back(start[1]); continue; } |
| yy233: |
| yych = *++p; |
| if (yybm[0+yych] & 64) { |
| goto yy233; |
| } |
| { expand(start + 1, p); continue; } |
| yy236: |
| yych = *++p; |
| if (yych == '}') goto yy230; |
| goto yy238; |
| yy237: |
| yych = *++p; |
| yy238: |
| if (yybm[0+yych] & 128) { |
| goto yy237; |
| } |
| if (yych != '}') goto yy230; |
| ++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; |
| } |