| Shinichiro Hamaji | 1d545aa | 2015-06-23 15:29:13 +0900 | [diff] [blame] | 1 | // Copyright 2015 Google Inc. All rights reserved | 
 | 2 | // | 
 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 4 | // you may not use this file except in compliance with the License. | 
 | 5 | // You may obtain a copy of the License at | 
 | 6 | // | 
 | 7 | //      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 8 | // | 
 | 9 | // Unless required by applicable law or agreed to in writing, software | 
 | 10 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 12 | // See the License for the specific language governing permissions and | 
 | 13 | // limitations under the License. | 
 | 14 |  | 
| Fumitoshi Ukai | 744bb2b | 2015-06-25 00:10:52 +0900 | [diff] [blame] | 15 | // +build ignore | 
 | 16 |  | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 17 | #include "parser.h" | 
 | 18 |  | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 19 | #include <stack> | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 20 | #include <unordered_map> | 
 | 21 |  | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 22 | #include "ast.h" | 
 | 23 | #include "file.h" | 
 | 24 | #include "loc.h" | 
 | 25 | #include "log.h" | 
| Shinichiro Hamaji | 6b1a11a | 2015-06-30 16:21:19 +0900 | [diff] [blame] | 26 | #include "stats.h" | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 27 | #include "string_piece.h" | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 28 | #include "strutil.h" | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 29 | #include "value.h" | 
 | 30 |  | 
 | 31 | enum struct ParserState { | 
 | 32 |   NOT_AFTER_RULE = 0, | 
 | 33 |   AFTER_RULE, | 
 | 34 |   MAYBE_AFTER_RULE, | 
 | 35 | }; | 
 | 36 |  | 
 | 37 | class Parser { | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 38 |   struct IfState { | 
 | 39 |     IfAST* ast; | 
 | 40 |     bool is_in_else; | 
 | 41 |     int num_nest; | 
 | 42 |   }; | 
 | 43 |  | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 44 |   typedef void (Parser::*DirectiveHandler)( | 
 | 45 |       StringPiece line, StringPiece directive); | 
 | 46 |   typedef unordered_map<StringPiece, DirectiveHandler> DirectiveMap; | 
 | 47 |  | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 48 |  public: | 
 | 49 |   Parser(StringPiece buf, const char* filename, vector<AST*>* asts) | 
 | 50 |       : buf_(buf), | 
 | 51 |         state_(ParserState::NOT_AFTER_RULE), | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 52 |         asts_(asts), | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 53 |         out_asts_(asts), | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 54 |         num_if_nest_(0), | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 55 |         loc_(filename, 0), | 
 | 56 |         fixed_lineno_(false) { | 
 | 57 |   } | 
 | 58 |  | 
| Shinichiro Hamaji | 80456fb | 2015-06-18 14:56:10 +0900 | [diff] [blame] | 59 |   Parser(StringPiece buf, const Loc& loc, vector<AST*>* asts) | 
 | 60 |       : buf_(buf), | 
 | 61 |         state_(ParserState::NOT_AFTER_RULE), | 
 | 62 |         asts_(asts), | 
 | 63 |         out_asts_(asts), | 
 | 64 |         num_if_nest_(0), | 
 | 65 |         loc_(loc), | 
 | 66 |         fixed_lineno_(true) { | 
 | 67 |   } | 
 | 68 |  | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 69 |   ~Parser() { | 
 | 70 |   } | 
 | 71 |  | 
 | 72 |   void Parse() { | 
 | 73 |     l_ = 0; | 
 | 74 |  | 
 | 75 |     for (l_ = 0; l_ < buf_.size();) { | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 76 |       size_t lf_cnt = 0; | 
 | 77 |       size_t e = FindEndOfLine(&lf_cnt); | 
| Shinichiro Hamaji | 8ee8c37 | 2015-06-16 16:19:40 +0900 | [diff] [blame] | 78 |       if (!fixed_lineno_) | 
| Shinichiro Hamaji | b3af68b | 2015-06-24 20:47:57 +0900 | [diff] [blame] | 79 |         loc_.lineno++; | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 80 |       StringPiece line(buf_.data() + l_, e - l_); | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 81 |       orig_line_with_directives_ = line; | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 82 |       ParseLine(line); | 
| Shinichiro Hamaji | b3af68b | 2015-06-24 20:47:57 +0900 | [diff] [blame] | 83 |       if (!fixed_lineno_) | 
 | 84 |         loc_.lineno += lf_cnt - 1; | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 85 |       if (e == buf_.size()) | 
 | 86 |         break; | 
 | 87 |  | 
 | 88 |       l_ = e + 1; | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 89 |     } | 
 | 90 |   } | 
 | 91 |  | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 92 |   static void Init() { | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 93 |     make_directives_ = new DirectiveMap; | 
| Shinichiro Hamaji | 14b8bea | 2015-06-17 03:14:28 +0900 | [diff] [blame] | 94 |     (*make_directives_)["include"] = &Parser::ParseInclude; | 
 | 95 |     (*make_directives_)["-include"] = &Parser::ParseInclude; | 
 | 96 |     (*make_directives_)["sinclude"] = &Parser::ParseInclude; | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 97 |     (*make_directives_)["define"] = &Parser::ParseDefine; | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 98 |     (*make_directives_)["ifdef"] = &Parser::ParseIfdef; | 
 | 99 |     (*make_directives_)["ifndef"] = &Parser::ParseIfdef; | 
| Shinichiro Hamaji | d146f4c | 2015-06-17 17:51:24 +0900 | [diff] [blame] | 100 |     (*make_directives_)["ifeq"] = &Parser::ParseIfeq; | 
 | 101 |     (*make_directives_)["ifneq"] = &Parser::ParseIfeq; | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 102 |     (*make_directives_)["else"] = &Parser::ParseElse; | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 103 |     (*make_directives_)["endif"] = &Parser::ParseEndif; | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 104 |     (*make_directives_)["override"] = &Parser::ParseOverride; | 
 | 105 |     (*make_directives_)["export"] = &Parser::ParseExport; | 
 | 106 |     (*make_directives_)["unexport"] = &Parser::ParseUnexport; | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 107 |  | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 108 |     else_if_directives_ = new DirectiveMap; | 
 | 109 |     (*else_if_directives_)["ifdef"] = &Parser::ParseIfdef; | 
 | 110 |     (*else_if_directives_)["ifndef"] = &Parser::ParseIfdef; | 
| Shinichiro Hamaji | 6aeab2a | 2015-06-26 09:12:01 +0900 | [diff] [blame] | 111 |     (*else_if_directives_)["ifeq"] = &Parser::ParseIfeq; | 
 | 112 |     (*else_if_directives_)["ifneq"] = &Parser::ParseIfeq; | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 113 |  | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 114 |     assign_directives_ = new DirectiveMap; | 
 | 115 |     (*assign_directives_)["define"] = &Parser::ParseDefine; | 
 | 116 |     (*assign_directives_)["export"] = &Parser::ParseExport; | 
 | 117 |     (*assign_directives_)["override"] = &Parser::ParseOverride; | 
 | 118 |  | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 119 |     shortest_directive_len_ = 9999; | 
 | 120 |     longest_directive_len_ = 0; | 
 | 121 |     for (auto p : *make_directives_) { | 
 | 122 |       size_t len = p.first.size(); | 
 | 123 |       shortest_directive_len_ = min(len, shortest_directive_len_); | 
 | 124 |       longest_directive_len_ = max(len, longest_directive_len_); | 
 | 125 |     } | 
 | 126 |   } | 
 | 127 |  | 
 | 128 |   static void Quit() { | 
 | 129 |     delete make_directives_; | 
 | 130 |   } | 
 | 131 |  | 
| Shinichiro Hamaji | 631a9f8 | 2015-07-05 14:18:15 +0900 | [diff] [blame] | 132 |   void set_state(ParserState st) { state_ = st; } | 
 | 133 |  | 
| Shinichiro Hamaji | a06bee9 | 2015-08-05 17:13:05 +0900 | [diff] [blame] | 134 |   static vector<ParseErrorAST*> parse_errors; | 
 | 135 |  | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 136 |  private: | 
 | 137 |   void Error(const string& msg) { | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 138 |     ParseErrorAST* ast = new ParseErrorAST(); | 
 | 139 |     ast->set_loc(loc_); | 
 | 140 |     ast->msg = msg; | 
 | 141 |     out_asts_->push_back(ast); | 
| Shinichiro Hamaji | a06bee9 | 2015-08-05 17:13:05 +0900 | [diff] [blame] | 142 |     parse_errors.push_back(ast); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 143 |   } | 
 | 144 |  | 
 | 145 |   size_t FindEndOfLine(size_t* lf_cnt) { | 
| Shinichiro Hamaji | 14bb279 | 2015-06-25 18:24:11 +0900 | [diff] [blame] | 146 |     return ::FindEndOfLine(buf_, l_, lf_cnt); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 147 |   } | 
 | 148 |  | 
| Shinichiro Hamaji | 36b326f | 2015-06-26 08:56:13 +0900 | [diff] [blame] | 149 |   Value* ParseExpr(StringPiece s, ParseExprOpt opt = ParseExprOpt::NORMAL) { | 
 | 150 |     return ::ParseExpr(loc_, s, opt); | 
 | 151 |   } | 
 | 152 |  | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 153 |   void ParseLine(StringPiece line) { | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 154 |     if (!define_name_.empty()) { | 
 | 155 |       ParseInsideDefine(line); | 
 | 156 |       return; | 
 | 157 |     } | 
 | 158 |  | 
| Shinichiro Hamaji | c6ac0b9 | 2015-07-06 16:24:10 +0900 | [diff] [blame] | 159 |     if (line.empty() || (line.size() == 1 && line[0] == '\r')) | 
 | 160 |       return; | 
 | 161 |  | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 162 |     current_directive_ = AssignDirective::NONE; | 
 | 163 |  | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 164 |     if (line[0] == '\t' && state_ != ParserState::NOT_AFTER_RULE) { | 
 | 165 |       CommandAST* ast = new CommandAST(); | 
| Shinichiro Hamaji | 861bd64 | 2015-06-19 16:59:13 +0900 | [diff] [blame] | 166 |       ast->set_loc(loc_); | 
| Shinichiro Hamaji | 66bd7bc | 2015-06-19 16:54:06 +0900 | [diff] [blame] | 167 |       ast->expr = ParseExpr(line.substr(1), ParseExprOpt::COMMAND); | 
| Shinichiro Hamaji | 631a9f8 | 2015-07-05 14:18:15 +0900 | [diff] [blame] | 168 |       ast->orig = line; | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 169 |       out_asts_->push_back(ast); | 
 | 170 |       return; | 
 | 171 |     } | 
 | 172 |  | 
| Shinichiro Hamaji | 3275062 | 2015-06-17 14:57:33 +0900 | [diff] [blame] | 173 |     line = TrimLeftSpace(line); | 
| Shinichiro Hamaji | d4e8193 | 2015-06-17 04:40:45 +0900 | [diff] [blame] | 174 |  | 
 | 175 |     if (line[0] == '#') | 
 | 176 |       return; | 
 | 177 |  | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 178 |     if (HandleDirective(line, make_directives_)) { | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 179 |       return; | 
 | 180 |     } | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 181 |  | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 182 |     ParseRuleOrAssign(line); | 
 | 183 |   } | 
 | 184 |  | 
 | 185 |   void ParseRuleOrAssign(StringPiece line) { | 
| Shinichiro Hamaji | 415a9b1 | 2015-07-05 14:33:02 +0900 | [diff] [blame] | 186 |     size_t sep = FindThreeOutsideParen(line, ':', '=', ';'); | 
 | 187 |     if (sep == string::npos || line[sep] == ';') { | 
 | 188 |       ParseRule(line, string::npos); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 189 |     } else if (line[sep] == '=') { | 
| Shinichiro Hamaji | 14b8bea | 2015-06-17 03:14:28 +0900 | [diff] [blame] | 190 |       ParseAssign(line, sep); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 191 |     } else if (line.get(sep+1) == '=') { | 
| Shinichiro Hamaji | 14b8bea | 2015-06-17 03:14:28 +0900 | [diff] [blame] | 192 |       ParseAssign(line, sep+1); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 193 |     } else if (line[sep] == ':') { | 
| Shinichiro Hamaji | 14b8bea | 2015-06-17 03:14:28 +0900 | [diff] [blame] | 194 |       ParseRule(line, sep); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 195 |     } else { | 
 | 196 |       CHECK(false); | 
 | 197 |     } | 
 | 198 |   } | 
 | 199 |  | 
| Shinichiro Hamaji | 14b8bea | 2015-06-17 03:14:28 +0900 | [diff] [blame] | 200 |   void ParseRule(StringPiece line, size_t sep) { | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 201 |     if (current_directive_ != AssignDirective::NONE) { | 
| Shinichiro Hamaji | 45a0c76 | 2015-06-26 06:47:10 +0900 | [diff] [blame] | 202 |       if (IsInExport()) | 
 | 203 |         return; | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 204 |       if (sep != string::npos) { | 
 | 205 |         sep += orig_line_with_directives_.size() - line.size(); | 
 | 206 |       } | 
 | 207 |       line = orig_line_with_directives_; | 
| Shinichiro Hamaji | df066c3 | 2015-06-26 09:09:26 +0900 | [diff] [blame] | 208 |     } | 
 | 209 |  | 
| Shinichiro Hamaji | 6aeab2a | 2015-06-26 09:12:01 +0900 | [diff] [blame] | 210 |     line = TrimLeftSpace(line); | 
| Shinichiro Hamaji | df066c3 | 2015-06-26 09:09:26 +0900 | [diff] [blame] | 211 |     if (line.empty()) | 
 | 212 |       return; | 
 | 213 |  | 
 | 214 |     if (orig_line_with_directives_[0] == '\t') { | 
| Shinichiro Hamaji | 2bed770 | 2015-06-26 07:56:28 +0900 | [diff] [blame] | 215 |       Error("*** commands commence before first target."); | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 216 |       return; | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 217 |     } | 
 | 218 |  | 
| Shinichiro Hamaji | 76ff983 | 2015-06-18 17:11:22 +0900 | [diff] [blame] | 219 |     const bool is_rule = sep != string::npos && line[sep] == ':'; | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 220 |     RuleAST* ast = new RuleAST(); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 221 |     ast->set_loc(loc_); | 
 | 222 |  | 
| Shinichiro Hamaji | 76ff983 | 2015-06-18 17:11:22 +0900 | [diff] [blame] | 223 |     size_t found = FindTwoOutsideParen(line.substr(sep + 1), '=', ';'); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 224 |     if (found != string::npos) { | 
 | 225 |       found += sep + 1; | 
 | 226 |       ast->term = line[found]; | 
| Shinichiro Hamaji | 66bd7bc | 2015-06-19 16:54:06 +0900 | [diff] [blame] | 227 |       ParseExprOpt opt = | 
 | 228 |           ast->term == ';' ? ParseExprOpt::COMMAND : ParseExprOpt::NORMAL; | 
 | 229 |       ast->after_term = ParseExpr(TrimLeftSpace(line.substr(found + 1)), opt); | 
 | 230 |       ast->expr = ParseExpr(TrimSpace(line.substr(0, found))); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 231 |     } else { | 
 | 232 |       ast->term = 0; | 
 | 233 |       ast->after_term = NULL; | 
| Shinichiro Hamaji | df066c3 | 2015-06-26 09:09:26 +0900 | [diff] [blame] | 234 |       ast->expr = ParseExpr(line); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 235 |     } | 
 | 236 |     out_asts_->push_back(ast); | 
 | 237 |     state_ = is_rule ? ParserState::AFTER_RULE : ParserState::MAYBE_AFTER_RULE; | 
 | 238 |   } | 
 | 239 |  | 
| Shinichiro Hamaji | 14b8bea | 2015-06-17 03:14:28 +0900 | [diff] [blame] | 240 |   void ParseAssign(StringPiece line, size_t sep) { | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 241 |     if (sep == 0) { | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 242 |       Error("*** empty variable name ***"); | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 243 |       return; | 
 | 244 |     } | 
| Shinichiro Hamaji | 9b16bda | 2015-06-19 14:25:17 +0900 | [diff] [blame] | 245 |     StringPiece lhs; | 
 | 246 |     StringPiece rhs; | 
 | 247 |     AssignOp op; | 
 | 248 |     ParseAssignStatement(line, sep, &lhs, &rhs, &op); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 249 |  | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 250 |     AssignAST* ast = new AssignAST(); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 251 |     ast->set_loc(loc_); | 
| Shinichiro Hamaji | 66bd7bc | 2015-06-19 16:54:06 +0900 | [diff] [blame] | 252 |     ast->lhs = ParseExpr(lhs); | 
 | 253 |     ast->rhs = ParseExpr(rhs); | 
| Shinichiro Hamaji | 81699be | 2015-06-22 18:07:38 +0900 | [diff] [blame] | 254 |     ast->orig_rhs = rhs; | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 255 |     ast->op = op; | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 256 |     ast->directive = current_directive_; | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 257 |     out_asts_->push_back(ast); | 
 | 258 |     state_ = ParserState::NOT_AFTER_RULE; | 
 | 259 |   } | 
 | 260 |  | 
| Shinichiro Hamaji | 14b8bea | 2015-06-17 03:14:28 +0900 | [diff] [blame] | 261 |   void ParseInclude(StringPiece line, StringPiece directive) { | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 262 |     IncludeAST* ast = new IncludeAST(); | 
| Shinichiro Hamaji | 861bd64 | 2015-06-19 16:59:13 +0900 | [diff] [blame] | 263 |     ast->set_loc(loc_); | 
| Shinichiro Hamaji | 66bd7bc | 2015-06-19 16:54:06 +0900 | [diff] [blame] | 264 |     ast->expr = ParseExpr(line); | 
| Shinichiro Hamaji | efad2dd | 2015-06-17 03:08:02 +0900 | [diff] [blame] | 265 |     ast->should_exist = directive[0] == 'i'; | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 266 |     out_asts_->push_back(ast); | 
| Shinichiro Hamaji | ff4584d | 2015-06-24 17:45:14 +0900 | [diff] [blame] | 267 |     state_ = ParserState::NOT_AFTER_RULE; | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 268 |   } | 
 | 269 |  | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 270 |   void ParseDefine(StringPiece line, StringPiece) { | 
 | 271 |     if (line.empty()) { | 
 | 272 |       Error("*** empty variable name."); | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 273 |       return; | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 274 |     } | 
 | 275 |     define_name_ = line; | 
 | 276 |     define_start_ = 0; | 
 | 277 |     define_start_line_ = loc_.lineno; | 
| Shinichiro Hamaji | ff4584d | 2015-06-24 17:45:14 +0900 | [diff] [blame] | 278 |     state_ = ParserState::NOT_AFTER_RULE; | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 279 |   } | 
 | 280 |  | 
 | 281 |   void ParseInsideDefine(StringPiece line) { | 
| Shinichiro Hamaji | 5562caf | 2015-06-17 17:08:40 +0900 | [diff] [blame] | 282 |     line = TrimLeftSpace(line); | 
 | 283 |     if (GetDirective(line) != "endef") { | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 284 |       if (define_start_ == 0) | 
 | 285 |         define_start_ = l_; | 
 | 286 |       return; | 
 | 287 |     } | 
 | 288 |  | 
| Shinichiro Hamaji | 5562caf | 2015-06-17 17:08:40 +0900 | [diff] [blame] | 289 |     StringPiece rest = TrimRightSpace(RemoveComment(TrimLeftSpace( | 
 | 290 |         line.substr(sizeof("endef"))))); | 
 | 291 |     if (!rest.empty()) { | 
 | 292 |       WARN("%s:%d: extraneous text after `endef' directive", LOCF(loc_)); | 
 | 293 |     } | 
 | 294 |  | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 295 |     AssignAST* ast = new AssignAST(); | 
 | 296 |     ast->set_loc(Loc(loc_.filename, define_start_line_)); | 
| Shinichiro Hamaji | 66bd7bc | 2015-06-19 16:54:06 +0900 | [diff] [blame] | 297 |     ast->lhs = ParseExpr(define_name_); | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 298 |     StringPiece rhs; | 
 | 299 |     if (define_start_) | 
| Shinichiro Hamaji | a4d0ecb | 2015-06-24 22:08:30 +0900 | [diff] [blame] | 300 |       rhs = buf_.substr(define_start_, l_ - define_start_ - 1); | 
| Shinichiro Hamaji | 66bd7bc | 2015-06-19 16:54:06 +0900 | [diff] [blame] | 301 |     ast->rhs = ParseExpr(rhs, ParseExprOpt::DEFINE); | 
| Shinichiro Hamaji | 81699be | 2015-06-22 18:07:38 +0900 | [diff] [blame] | 302 |     ast->orig_rhs = rhs; | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 303 |     ast->op = AssignOp::EQ; | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 304 |     ast->directive = current_directive_; | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 305 |     out_asts_->push_back(ast); | 
 | 306 |     define_name_.clear(); | 
 | 307 |   } | 
 | 308 |  | 
| Shinichiro Hamaji | d146f4c | 2015-06-17 17:51:24 +0900 | [diff] [blame] | 309 |   void EnterIf(IfAST* ast) { | 
 | 310 |     IfState* st = new IfState(); | 
 | 311 |     st->ast = ast; | 
 | 312 |     st->is_in_else = false; | 
 | 313 |     st->num_nest = num_if_nest_; | 
 | 314 |     if_stack_.push(st); | 
 | 315 |     out_asts_ = &ast->true_asts; | 
 | 316 |   } | 
 | 317 |  | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 318 |   void ParseIfdef(StringPiece line, StringPiece directive) { | 
 | 319 |     IfAST* ast = new IfAST(); | 
 | 320 |     ast->set_loc(loc_); | 
 | 321 |     ast->op = directive[2] == 'n' ? CondOp::IFNDEF : CondOp::IFDEF; | 
| Shinichiro Hamaji | 66bd7bc | 2015-06-19 16:54:06 +0900 | [diff] [blame] | 322 |     ast->lhs = ParseExpr(line); | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 323 |     ast->rhs = NULL; | 
 | 324 |     out_asts_->push_back(ast); | 
| Shinichiro Hamaji | d146f4c | 2015-06-17 17:51:24 +0900 | [diff] [blame] | 325 |     EnterIf(ast); | 
 | 326 |   } | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 327 |  | 
| Shinichiro Hamaji | d146f4c | 2015-06-17 17:51:24 +0900 | [diff] [blame] | 328 |   bool ParseIfEqCond(StringPiece s, IfAST* ast) { | 
 | 329 |     if (s.empty()) { | 
 | 330 |       return false; | 
 | 331 |     } | 
 | 332 |  | 
 | 333 |     if (s[0] == '(' && s[s.size() - 1] == ')') { | 
 | 334 |       s = s.substr(1, s.size() - 2); | 
 | 335 |       char terms[] = {',', '\0'}; | 
 | 336 |       size_t n; | 
| Shinichiro Hamaji | 36b326f | 2015-06-26 08:56:13 +0900 | [diff] [blame] | 337 |       ast->lhs = ParseExprImpl(loc_, s, terms, ParseExprOpt::NORMAL, &n, true); | 
| Shinichiro Hamaji | d146f4c | 2015-06-17 17:51:24 +0900 | [diff] [blame] | 338 |       if (s[n] != ',') | 
 | 339 |         return false; | 
 | 340 |       s = TrimLeftSpace(s.substr(n+1)); | 
| Shinichiro Hamaji | 36b326f | 2015-06-26 08:56:13 +0900 | [diff] [blame] | 341 |       ast->rhs = ParseExprImpl(loc_, s, NULL, ParseExprOpt::NORMAL, &n); | 
| Shinichiro Hamaji | adeea69 | 2015-06-17 17:57:31 +0900 | [diff] [blame] | 342 |       s = TrimLeftSpace(s.substr(n)); | 
| Shinichiro Hamaji | d146f4c | 2015-06-17 17:51:24 +0900 | [diff] [blame] | 343 |     } else { | 
 | 344 |       for (int i = 0; i < 2; i++) { | 
 | 345 |         if (s.empty()) | 
 | 346 |           return false; | 
 | 347 |         char quote = s[0]; | 
 | 348 |         if (quote != '\'' && quote != '"') | 
 | 349 |           return false; | 
 | 350 |         size_t end = s.find(quote, 1); | 
 | 351 |         if (end == string::npos) | 
 | 352 |           return false; | 
| Shinichiro Hamaji | 66bd7bc | 2015-06-19 16:54:06 +0900 | [diff] [blame] | 353 |         Value* v = ParseExpr(s.substr(1, end - 1), ParseExprOpt::NORMAL); | 
| Shinichiro Hamaji | d146f4c | 2015-06-17 17:51:24 +0900 | [diff] [blame] | 354 |         if (i == 0) | 
 | 355 |           ast->lhs = v; | 
 | 356 |         else | 
 | 357 |           ast->rhs = v; | 
 | 358 |         s = TrimLeftSpace(s.substr(end+1)); | 
 | 359 |       } | 
| Shinichiro Hamaji | d146f4c | 2015-06-17 17:51:24 +0900 | [diff] [blame] | 360 |     } | 
| Shinichiro Hamaji | adeea69 | 2015-06-17 17:57:31 +0900 | [diff] [blame] | 361 |     if (!s.empty()) { | 
| Shinichiro Hamaji | 00496aa | 2015-09-09 18:27:28 +0900 | [diff] [blame] | 362 |       WARN("%s:%d: extraneous text after `ifeq' directive", LOCF(loc_)); | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 363 |       return true; | 
| Shinichiro Hamaji | adeea69 | 2015-06-17 17:57:31 +0900 | [diff] [blame] | 364 |     } | 
 | 365 |     return true; | 
| Shinichiro Hamaji | d146f4c | 2015-06-17 17:51:24 +0900 | [diff] [blame] | 366 |   } | 
 | 367 |  | 
 | 368 |   void ParseIfeq(StringPiece line, StringPiece directive) { | 
 | 369 |     IfAST* ast = new IfAST(); | 
 | 370 |     ast->set_loc(loc_); | 
 | 371 |     ast->op = directive[2] == 'n' ? CondOp::IFNEQ : CondOp::IFEQ; | 
 | 372 |  | 
 | 373 |     if (!ParseIfEqCond(line, ast)) { | 
 | 374 |       Error("*** invalid syntax in conditional."); | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 375 |       return; | 
| Shinichiro Hamaji | d146f4c | 2015-06-17 17:51:24 +0900 | [diff] [blame] | 376 |     } | 
 | 377 |  | 
 | 378 |     out_asts_->push_back(ast); | 
 | 379 |     EnterIf(ast); | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 380 |   } | 
 | 381 |  | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 382 |   void ParseElse(StringPiece line, StringPiece) { | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 383 |     if (!CheckIfStack("else")) | 
 | 384 |       return; | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 385 |     IfState* st = if_stack_.top(); | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 386 |     if (st->is_in_else) { | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 387 |       Error("*** only one `else' per conditional."); | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 388 |       return; | 
 | 389 |     } | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 390 |     st->is_in_else = true; | 
 | 391 |     out_asts_ = &st->ast->false_asts; | 
 | 392 |  | 
 | 393 |     StringPiece next_if = TrimLeftSpace(line); | 
 | 394 |     if (next_if.empty()) | 
 | 395 |       return; | 
 | 396 |  | 
 | 397 |     num_if_nest_ = st->num_nest + 1; | 
 | 398 |     if (!HandleDirective(next_if, else_if_directives_)) { | 
 | 399 |       WARN("%s:%d: extraneous text after `else' directive", LOCF(loc_)); | 
 | 400 |     } | 
 | 401 |     num_if_nest_ = 0; | 
 | 402 |   } | 
 | 403 |  | 
 | 404 |   void ParseEndif(StringPiece line, StringPiece) { | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 405 |     if (!CheckIfStack("endif")) | 
 | 406 |       return; | 
 | 407 |     if (!line.empty()) { | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 408 |       Error("extraneous text after `endif` directive"); | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 409 |       return; | 
 | 410 |     } | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 411 |     IfState st = *if_stack_.top(); | 
 | 412 |     for (int t = 0; t <= st.num_nest; t++) { | 
 | 413 |       delete if_stack_.top(); | 
 | 414 |       if_stack_.pop(); | 
 | 415 |       if (if_stack_.empty()) { | 
 | 416 |         out_asts_ = asts_; | 
 | 417 |       } else { | 
 | 418 |         IfState* st = if_stack_.top(); | 
 | 419 |         if (st->is_in_else) | 
| Shinichiro Hamaji | 2847f09 | 2015-06-17 15:48:37 +0900 | [diff] [blame] | 420 |           out_asts_ = &st->ast->false_asts; | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 421 |         else | 
| Shinichiro Hamaji | 2847f09 | 2015-06-17 15:48:37 +0900 | [diff] [blame] | 422 |           out_asts_ = &st->ast->true_asts; | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 423 |       } | 
 | 424 |     } | 
 | 425 |   } | 
 | 426 |  | 
| Shinichiro Hamaji | 45a0c76 | 2015-06-26 06:47:10 +0900 | [diff] [blame] | 427 |   bool IsInExport() const { | 
 | 428 |     return (static_cast<int>(current_directive_) & | 
 | 429 |             static_cast<int>(AssignDirective::EXPORT)); | 
 | 430 |   } | 
 | 431 |  | 
 | 432 |   void CreateExport(StringPiece line, bool is_export) { | 
 | 433 |     ExportAST* ast = new ExportAST; | 
 | 434 |     ast->set_loc(loc_); | 
 | 435 |     ast->expr = ParseExpr(line); | 
 | 436 |     ast->is_export = is_export; | 
 | 437 |     out_asts_->push_back(ast); | 
 | 438 |   } | 
 | 439 |  | 
 | 440 |   void ParseOverride(StringPiece line, StringPiece) { | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 441 |     current_directive_ = | 
 | 442 |         static_cast<AssignDirective>( | 
 | 443 |             (static_cast<int>(current_directive_) | | 
 | 444 |              static_cast<int>(AssignDirective::OVERRIDE))); | 
 | 445 |     if (HandleDirective(line, assign_directives_)) | 
 | 446 |       return; | 
| Shinichiro Hamaji | 45a0c76 | 2015-06-26 06:47:10 +0900 | [diff] [blame] | 447 |     if (IsInExport()) { | 
 | 448 |       CreateExport(line, true); | 
 | 449 |     } | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 450 |     ParseRuleOrAssign(line); | 
 | 451 |   } | 
 | 452 |  | 
 | 453 |   void ParseExport(StringPiece line, StringPiece) { | 
| Shinichiro Hamaji | 45a0c76 | 2015-06-26 06:47:10 +0900 | [diff] [blame] | 454 |     current_directive_ = | 
 | 455 |         static_cast<AssignDirective>( | 
 | 456 |             (static_cast<int>(current_directive_) | | 
 | 457 |              static_cast<int>(AssignDirective::EXPORT))); | 
 | 458 |     if (HandleDirective(line, assign_directives_)) | 
 | 459 |       return; | 
 | 460 |     CreateExport(line, true); | 
 | 461 |     ParseRuleOrAssign(line); | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 462 |   } | 
 | 463 |  | 
 | 464 |   void ParseUnexport(StringPiece line, StringPiece) { | 
| Shinichiro Hamaji | 45a0c76 | 2015-06-26 06:47:10 +0900 | [diff] [blame] | 465 |     CreateExport(line, false); | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 466 |   } | 
 | 467 |  | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 468 |   bool CheckIfStack(const char* keyword) { | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 469 |     if (if_stack_.empty()) { | 
 | 470 |       Error(StringPrintf("*** extraneous `%s'.", keyword)); | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 471 |       return false; | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 472 |     } | 
| Shinichiro Hamaji | 5622786 | 2015-08-05 16:53:37 +0900 | [diff] [blame] | 473 |     return true; | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 474 |   } | 
 | 475 |  | 
| Shinichiro Hamaji | 5562caf | 2015-06-17 17:08:40 +0900 | [diff] [blame] | 476 |   StringPiece RemoveComment(StringPiece line) { | 
| Shinichiro Hamaji | eafd052 | 2015-06-18 16:46:02 +0900 | [diff] [blame] | 477 |     size_t i = FindOutsideParen(line, '#'); | 
 | 478 |     if (i == string::npos) | 
 | 479 |       return line; | 
 | 480 |     return line.substr(0, i); | 
| Shinichiro Hamaji | 5562caf | 2015-06-17 17:08:40 +0900 | [diff] [blame] | 481 |   } | 
 | 482 |  | 
 | 483 |   StringPiece GetDirective(StringPiece line) { | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 484 |     if (line.size() < shortest_directive_len_) | 
| Shinichiro Hamaji | 5562caf | 2015-06-17 17:08:40 +0900 | [diff] [blame] | 485 |       return StringPiece(); | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 486 |     StringPiece prefix = line.substr(0, longest_directive_len_ + 1); | 
| Shinichiro Hamaji | 5562caf | 2015-06-17 17:08:40 +0900 | [diff] [blame] | 487 |     size_t space_index = prefix.find_first_of(" \t#"); | 
 | 488 |     return prefix.substr(0, space_index); | 
 | 489 |   } | 
 | 490 |  | 
 | 491 |   bool HandleDirective(StringPiece line, const DirectiveMap* directive_map) { | 
 | 492 |     StringPiece directive = GetDirective(line); | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 493 |     auto found = directive_map->find(directive); | 
 | 494 |     if (found == directive_map->end()) | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 495 |       return false; | 
 | 496 |  | 
| Shinichiro Hamaji | 5562caf | 2015-06-17 17:08:40 +0900 | [diff] [blame] | 497 |     StringPiece rest = TrimRightSpace(RemoveComment(TrimLeftSpace( | 
| Shinichiro Hamaji | d146f4c | 2015-06-17 17:51:24 +0900 | [diff] [blame] | 498 |         line.substr(directive.size())))); | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 499 |     (this->*found->second)(rest, directive); | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 500 |     return true; | 
 | 501 |   } | 
 | 502 |  | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 503 |   StringPiece buf_; | 
 | 504 |   size_t l_; | 
 | 505 |   ParserState state_; | 
 | 506 |  | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 507 |   vector<AST*>* asts_; | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 508 |   vector<AST*>* out_asts_; | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 509 |  | 
| Shinichiro Hamaji | 810fd03 | 2015-06-17 04:38:03 +0900 | [diff] [blame] | 510 |   StringPiece define_name_; | 
 | 511 |   size_t define_start_; | 
 | 512 |   int define_start_line_; | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 513 |  | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 514 |   StringPiece orig_line_with_directives_; | 
 | 515 |   AssignDirective current_directive_; | 
 | 516 |  | 
| Shinichiro Hamaji | 7e256df | 2015-06-17 15:33:11 +0900 | [diff] [blame] | 517 |   int num_if_nest_; | 
 | 518 |   stack<IfState*> if_stack_; | 
 | 519 |  | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 520 |   Loc loc_; | 
 | 521 |   bool fixed_lineno_; | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 522 |  | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 523 |   static DirectiveMap* make_directives_; | 
 | 524 |   static DirectiveMap* else_if_directives_; | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 525 |   static DirectiveMap* assign_directives_; | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 526 |   static size_t shortest_directive_len_; | 
 | 527 |   static size_t longest_directive_len_; | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 528 | }; | 
 | 529 |  | 
 | 530 | void Parse(Makefile* mk) { | 
| Shinichiro Hamaji | 6b1a11a | 2015-06-30 16:21:19 +0900 | [diff] [blame] | 531 |   COLLECT_STATS("parse file time"); | 
| Shinichiro Hamaji | 776ca30 | 2015-06-06 03:52:48 +0900 | [diff] [blame] | 532 |   Parser parser(StringPiece(mk->buf(), mk->len()), | 
 | 533 |                 mk->filename().c_str(), | 
 | 534 |                 mk->mutable_asts()); | 
 | 535 |   parser.Parse(); | 
 | 536 | } | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 537 |  | 
| Shinichiro Hamaji | 80456fb | 2015-06-18 14:56:10 +0900 | [diff] [blame] | 538 | void Parse(StringPiece buf, const Loc& loc, vector<AST*>* out_asts) { | 
| Shinichiro Hamaji | 6b1a11a | 2015-06-30 16:21:19 +0900 | [diff] [blame] | 539 |   COLLECT_STATS("parse eval time"); | 
| Shinichiro Hamaji | 80456fb | 2015-06-18 14:56:10 +0900 | [diff] [blame] | 540 |   Parser parser(buf, loc, out_asts); | 
 | 541 |   parser.Parse(); | 
 | 542 | } | 
 | 543 |  | 
| Shinichiro Hamaji | 631a9f8 | 2015-07-05 14:18:15 +0900 | [diff] [blame] | 544 | void ParseNotAfterRule(StringPiece buf, const Loc& loc, | 
 | 545 |                        vector<AST*>* out_asts) { | 
 | 546 |   Parser parser(buf, loc, out_asts); | 
 | 547 |   parser.set_state(ParserState::NOT_AFTER_RULE); | 
 | 548 |   parser.Parse(); | 
 | 549 | } | 
 | 550 |  | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 551 | void InitParser() { | 
 | 552 |   Parser::Init(); | 
 | 553 | } | 
 | 554 |  | 
 | 555 | void QuitParser() { | 
 | 556 |   Parser::Quit(); | 
 | 557 | } | 
 | 558 |  | 
| Shinichiro Hamaji | 6cb1c25 | 2015-06-17 16:22:51 +0900 | [diff] [blame] | 559 | Parser::DirectiveMap* Parser::make_directives_; | 
 | 560 | Parser::DirectiveMap* Parser::else_if_directives_; | 
| Shinichiro Hamaji | 420f775 | 2015-06-26 04:02:02 +0900 | [diff] [blame] | 561 | Parser::DirectiveMap* Parser::assign_directives_; | 
| Shinichiro Hamaji | 42b625f | 2015-06-16 23:07:21 +0900 | [diff] [blame] | 562 | size_t Parser::shortest_directive_len_; | 
 | 563 | size_t Parser::longest_directive_len_; | 
| Shinichiro Hamaji | a06bee9 | 2015-08-05 17:13:05 +0900 | [diff] [blame] | 564 | vector<ParseErrorAST*> Parser::parse_errors; | 
| Shinichiro Hamaji | 9b16bda | 2015-06-19 14:25:17 +0900 | [diff] [blame] | 565 |  | 
 | 566 | void ParseAssignStatement(StringPiece line, size_t sep, | 
 | 567 |                           StringPiece* lhs, StringPiece* rhs, AssignOp* op) { | 
 | 568 |   CHECK(sep != 0); | 
 | 569 |   *op = AssignOp::EQ; | 
 | 570 |   size_t lhs_end = sep; | 
 | 571 |   switch (line[sep-1]) { | 
 | 572 |     case ':': | 
 | 573 |       lhs_end--; | 
 | 574 |       *op = AssignOp::COLON_EQ; | 
 | 575 |       break; | 
 | 576 |     case '+': | 
 | 577 |       lhs_end--; | 
 | 578 |       *op = AssignOp::PLUS_EQ; | 
 | 579 |       break; | 
 | 580 |     case '?': | 
 | 581 |       lhs_end--; | 
 | 582 |       *op = AssignOp::QUESTION_EQ; | 
 | 583 |       break; | 
 | 584 |   } | 
 | 585 |   *lhs = TrimSpace(line.substr(0, lhs_end)); | 
 | 586 |   *rhs = TrimSpace(line.substr(sep + 1)); | 
 | 587 | } | 
| Shinichiro Hamaji | a06bee9 | 2015-08-05 17:13:05 +0900 | [diff] [blame] | 588 |  | 
 | 589 | const vector<ParseErrorAST*>& GetParseErrors() { | 
 | 590 |   return Parser::parse_errors; | 
 | 591 | } |