blob: 96b8ba365b5b1e72531e0d6b69d00a7506c734cc [file] [log] [blame]
Shinichiro Hamaji1d545aa2015-06-23 15:29:13 +09001// 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 Ukai744bb2b2015-06-25 00:10:52 +090015// +build ignore
16
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090017#include "parser.h"
18
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090019#include <stack>
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +090020#include <unordered_map>
21
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090022#include "expr.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090023#include "file.h"
24#include "loc.h"
25#include "log.h"
Shinichiro Hamaji6b1a11a2015-06-30 16:21:19 +090026#include "stats.h"
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090027#include "stmt.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090028#include "string_piece.h"
Shinichiro Hamaji810fd032015-06-17 04:38:03 +090029#include "strutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090030
31enum struct ParserState {
32 NOT_AFTER_RULE = 0,
33 AFTER_RULE,
34 MAYBE_AFTER_RULE,
35};
36
37class Parser {
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090038 struct IfState {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090039 IfStmt* stmt;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090040 bool is_in_else;
41 int num_nest;
42 };
43
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +090044 typedef void (Parser::*DirectiveHandler)(
45 StringPiece line, StringPiece directive);
46 typedef unordered_map<StringPiece, DirectiveHandler> DirectiveMap;
47
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090048 public:
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090049 Parser(StringPiece buf, const char* filename, vector<Stmt*>* stmts)
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090050 : buf_(buf),
51 state_(ParserState::NOT_AFTER_RULE),
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090052 stmts_(stmts),
53 out_stmts_(stmts),
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090054 num_if_nest_(0),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090055 loc_(filename, 0),
56 fixed_lineno_(false) {
57 }
58
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090059 Parser(StringPiece buf, const Loc& loc, vector<Stmt*>* stmts)
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +090060 : buf_(buf),
61 state_(ParserState::NOT_AFTER_RULE),
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090062 stmts_(stmts),
63 out_stmts_(stmts),
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +090064 num_if_nest_(0),
65 loc_(loc),
66 fixed_lineno_(true) {
67 }
68
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090069 ~Parser() {
70 }
71
72 void Parse() {
73 l_ = 0;
74
75 for (l_ = 0; l_ < buf_.size();) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090076 size_t lf_cnt = 0;
77 size_t e = FindEndOfLine(&lf_cnt);
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +090078 if (!fixed_lineno_)
Shinichiro Hamajib3af68b2015-06-24 20:47:57 +090079 loc_.lineno++;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090080 StringPiece line(buf_.data() + l_, e - l_);
Shinichiro Hamaji420f7752015-06-26 04:02:02 +090081 orig_line_with_directives_ = line;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090082 ParseLine(line);
Shinichiro Hamajib3af68b2015-06-24 20:47:57 +090083 if (!fixed_lineno_)
84 loc_.lineno += lf_cnt - 1;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090085 if (e == buf_.size())
86 break;
87
88 l_ = e + 1;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090089 }
Shinichiro Hamaji083fd262016-04-09 12:28:34 +090090
91 if (!if_stack_.empty())
92 ERROR("%s:%d: *** missing `endif'.", loc_.filename, loc_.lineno + 1);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090093 }
94
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +090095 static void Init() {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +090096 make_directives_ = new DirectiveMap;
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +090097 (*make_directives_)["include"] = &Parser::ParseInclude;
98 (*make_directives_)["-include"] = &Parser::ParseInclude;
99 (*make_directives_)["sinclude"] = &Parser::ParseInclude;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900100 (*make_directives_)["define"] = &Parser::ParseDefine;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900101 (*make_directives_)["ifdef"] = &Parser::ParseIfdef;
102 (*make_directives_)["ifndef"] = &Parser::ParseIfdef;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900103 (*make_directives_)["ifeq"] = &Parser::ParseIfeq;
104 (*make_directives_)["ifneq"] = &Parser::ParseIfeq;
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900105 (*make_directives_)["else"] = &Parser::ParseElse;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900106 (*make_directives_)["endif"] = &Parser::ParseEndif;
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900107 (*make_directives_)["override"] = &Parser::ParseOverride;
108 (*make_directives_)["export"] = &Parser::ParseExport;
109 (*make_directives_)["unexport"] = &Parser::ParseUnexport;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900110
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900111 else_if_directives_ = new DirectiveMap;
112 (*else_if_directives_)["ifdef"] = &Parser::ParseIfdef;
113 (*else_if_directives_)["ifndef"] = &Parser::ParseIfdef;
Shinichiro Hamaji6aeab2a2015-06-26 09:12:01 +0900114 (*else_if_directives_)["ifeq"] = &Parser::ParseIfeq;
115 (*else_if_directives_)["ifneq"] = &Parser::ParseIfeq;
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900116
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900117 assign_directives_ = new DirectiveMap;
118 (*assign_directives_)["define"] = &Parser::ParseDefine;
119 (*assign_directives_)["export"] = &Parser::ParseExport;
120 (*assign_directives_)["override"] = &Parser::ParseOverride;
121
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900122 shortest_directive_len_ = 9999;
123 longest_directive_len_ = 0;
124 for (auto p : *make_directives_) {
125 size_t len = p.first.size();
126 shortest_directive_len_ = min(len, shortest_directive_len_);
127 longest_directive_len_ = max(len, longest_directive_len_);
128 }
129 }
130
131 static void Quit() {
132 delete make_directives_;
133 }
134
Shinichiro Hamaji631a9f82015-07-05 14:18:15 +0900135 void set_state(ParserState st) { state_ = st; }
136
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900137 static vector<ParseErrorStmt*> parse_errors;
Shinichiro Hamajia06bee92015-08-05 17:13:05 +0900138
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900139 private:
140 void Error(const string& msg) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900141 ParseErrorStmt* stmt = new ParseErrorStmt();
142 stmt->set_loc(loc_);
143 stmt->msg = msg;
144 out_stmts_->push_back(stmt);
145 parse_errors.push_back(stmt);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900146 }
147
148 size_t FindEndOfLine(size_t* lf_cnt) {
Shinichiro Hamaji14bb2792015-06-25 18:24:11 +0900149 return ::FindEndOfLine(buf_, l_, lf_cnt);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900150 }
151
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900152 Value* ParseExpr(StringPiece s, ParseExprOpt opt = ParseExprOpt::NORMAL) {
153 return ::ParseExpr(loc_, s, opt);
154 }
155
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900156 void ParseLine(StringPiece line) {
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900157 if (!define_name_.empty()) {
158 ParseInsideDefine(line);
159 return;
160 }
161
Shinichiro Hamajic6ac0b92015-07-06 16:24:10 +0900162 if (line.empty() || (line.size() == 1 && line[0] == '\r'))
163 return;
164
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900165 current_directive_ = AssignDirective::NONE;
166
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900167 if (line[0] == '\t' && state_ != ParserState::NOT_AFTER_RULE) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900168 CommandStmt* stmt = new CommandStmt();
169 stmt->set_loc(loc_);
170 stmt->expr = ParseExpr(line.substr(1), ParseExprOpt::COMMAND);
171 stmt->orig = line;
172 out_stmts_->push_back(stmt);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900173 return;
174 }
175
Shinichiro Hamaji32750622015-06-17 14:57:33 +0900176 line = TrimLeftSpace(line);
Shinichiro Hamajid4e81932015-06-17 04:40:45 +0900177
178 if (line[0] == '#')
179 return;
180
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900181 if (HandleDirective(line, make_directives_)) {
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900182 return;
183 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900184
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900185 ParseRuleOrAssign(line);
186 }
187
188 void ParseRuleOrAssign(StringPiece line) {
Shinichiro Hamaji415a9b12015-07-05 14:33:02 +0900189 size_t sep = FindThreeOutsideParen(line, ':', '=', ';');
190 if (sep == string::npos || line[sep] == ';') {
191 ParseRule(line, string::npos);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900192 } else if (line[sep] == '=') {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900193 ParseAssign(line, sep);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900194 } else if (line.get(sep+1) == '=') {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900195 ParseAssign(line, sep+1);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900196 } else if (line[sep] == ':') {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900197 ParseRule(line, sep);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900198 } else {
199 CHECK(false);
200 }
201 }
202
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900203 void ParseRule(StringPiece line, size_t sep) {
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900204 if (current_directive_ != AssignDirective::NONE) {
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900205 if (IsInExport())
206 return;
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900207 if (sep != string::npos) {
208 sep += orig_line_with_directives_.size() - line.size();
209 }
210 line = orig_line_with_directives_;
Shinichiro Hamajidf066c32015-06-26 09:09:26 +0900211 }
212
Shinichiro Hamaji6aeab2a2015-06-26 09:12:01 +0900213 line = TrimLeftSpace(line);
Shinichiro Hamajidf066c32015-06-26 09:09:26 +0900214 if (line.empty())
215 return;
216
217 if (orig_line_with_directives_[0] == '\t') {
Shinichiro Hamaji2bed7702015-06-26 07:56:28 +0900218 Error("*** commands commence before first target.");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900219 return;
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900220 }
221
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900222 const bool is_rule = sep != string::npos && line[sep] == ':';
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900223 RuleStmt* stmt = new RuleStmt();
224 stmt->set_loc(loc_);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900225
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900226 size_t found = FindTwoOutsideParen(line.substr(sep + 1), '=', ';');
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900227 if (found != string::npos) {
228 found += sep + 1;
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900229 stmt->term = line[found];
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900230 ParseExprOpt opt =
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900231 stmt->term == ';' ? ParseExprOpt::COMMAND : ParseExprOpt::NORMAL;
232 stmt->after_term = ParseExpr(TrimLeftSpace(line.substr(found + 1)), opt);
233 stmt->expr = ParseExpr(TrimSpace(line.substr(0, found)));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900234 } else {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900235 stmt->term = 0;
236 stmt->after_term = NULL;
237 stmt->expr = ParseExpr(line);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900238 }
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900239 out_stmts_->push_back(stmt);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900240 state_ = is_rule ? ParserState::AFTER_RULE : ParserState::MAYBE_AFTER_RULE;
241 }
242
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900243 void ParseAssign(StringPiece line, size_t sep) {
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900244 if (sep == 0) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900245 Error("*** empty variable name ***");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900246 return;
247 }
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900248 StringPiece lhs;
249 StringPiece rhs;
250 AssignOp op;
251 ParseAssignStatement(line, sep, &lhs, &rhs, &op);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900252
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900253 AssignStmt* stmt = new AssignStmt();
254 stmt->set_loc(loc_);
255 stmt->lhs = ParseExpr(lhs);
256 stmt->rhs = ParseExpr(rhs);
257 stmt->orig_rhs = rhs;
258 stmt->op = op;
259 stmt->directive = current_directive_;
260 out_stmts_->push_back(stmt);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900261 state_ = ParserState::NOT_AFTER_RULE;
262 }
263
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900264 void ParseInclude(StringPiece line, StringPiece directive) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900265 IncludeStmt* stmt = new IncludeStmt();
266 stmt->set_loc(loc_);
267 stmt->expr = ParseExpr(line);
268 stmt->should_exist = directive[0] == 'i';
269 out_stmts_->push_back(stmt);
Shinichiro Hamajiff4584d2015-06-24 17:45:14 +0900270 state_ = ParserState::NOT_AFTER_RULE;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900271 }
272
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900273 void ParseDefine(StringPiece line, StringPiece) {
274 if (line.empty()) {
275 Error("*** empty variable name.");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900276 return;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900277 }
278 define_name_ = line;
279 define_start_ = 0;
280 define_start_line_ = loc_.lineno;
Shinichiro Hamajiff4584d2015-06-24 17:45:14 +0900281 state_ = ParserState::NOT_AFTER_RULE;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900282 }
283
284 void ParseInsideDefine(StringPiece line) {
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900285 line = TrimLeftSpace(line);
286 if (GetDirective(line) != "endef") {
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900287 if (define_start_ == 0)
288 define_start_ = l_;
289 return;
290 }
291
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900292 StringPiece rest = TrimRightSpace(RemoveComment(TrimLeftSpace(
293 line.substr(sizeof("endef")))));
294 if (!rest.empty()) {
295 WARN("%s:%d: extraneous text after `endef' directive", LOCF(loc_));
296 }
297
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900298 AssignStmt* stmt = new AssignStmt();
299 stmt->set_loc(Loc(loc_.filename, define_start_line_));
300 stmt->lhs = ParseExpr(define_name_);
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900301 StringPiece rhs;
302 if (define_start_)
Shinichiro Hamajia4d0ecb2015-06-24 22:08:30 +0900303 rhs = buf_.substr(define_start_, l_ - define_start_ - 1);
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900304 stmt->rhs = ParseExpr(rhs, ParseExprOpt::DEFINE);
305 stmt->orig_rhs = rhs;
306 stmt->op = AssignOp::EQ;
307 stmt->directive = current_directive_;
308 out_stmts_->push_back(stmt);
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900309 define_name_.clear();
310 }
311
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900312 void EnterIf(IfStmt* stmt) {
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900313 IfState* st = new IfState();
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900314 st->stmt = stmt;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900315 st->is_in_else = false;
316 st->num_nest = num_if_nest_;
317 if_stack_.push(st);
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900318 out_stmts_ = &stmt->true_stmts;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900319 }
320
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900321 void ParseIfdef(StringPiece line, StringPiece directive) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900322 IfStmt* stmt = new IfStmt();
323 stmt->set_loc(loc_);
324 stmt->op = directive[2] == 'n' ? CondOp::IFNDEF : CondOp::IFDEF;
325 stmt->lhs = ParseExpr(line);
326 stmt->rhs = NULL;
327 out_stmts_->push_back(stmt);
328 EnterIf(stmt);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900329 }
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900330
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900331 bool ParseIfEqCond(StringPiece s, IfStmt* stmt) {
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900332 if (s.empty()) {
333 return false;
334 }
335
336 if (s[0] == '(' && s[s.size() - 1] == ')') {
337 s = s.substr(1, s.size() - 2);
338 char terms[] = {',', '\0'};
339 size_t n;
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900340 stmt->lhs = ParseExprImpl(loc_, s, terms, ParseExprOpt::NORMAL, &n, true);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900341 if (s[n] != ',')
342 return false;
343 s = TrimLeftSpace(s.substr(n+1));
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900344 stmt->rhs = ParseExprImpl(loc_, s, NULL, ParseExprOpt::NORMAL, &n);
Shinichiro Hamajiadeea692015-06-17 17:57:31 +0900345 s = TrimLeftSpace(s.substr(n));
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900346 } else {
347 for (int i = 0; i < 2; i++) {
348 if (s.empty())
349 return false;
350 char quote = s[0];
351 if (quote != '\'' && quote != '"')
352 return false;
353 size_t end = s.find(quote, 1);
354 if (end == string::npos)
355 return false;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900356 Value* v = ParseExpr(s.substr(1, end - 1), ParseExprOpt::NORMAL);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900357 if (i == 0)
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900358 stmt->lhs = v;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900359 else
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900360 stmt->rhs = v;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900361 s = TrimLeftSpace(s.substr(end+1));
362 }
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900363 }
Shinichiro Hamajiadeea692015-06-17 17:57:31 +0900364 if (!s.empty()) {
Shinichiro Hamaji00496aa2015-09-09 18:27:28 +0900365 WARN("%s:%d: extraneous text after `ifeq' directive", LOCF(loc_));
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900366 return true;
Shinichiro Hamajiadeea692015-06-17 17:57:31 +0900367 }
368 return true;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900369 }
370
371 void ParseIfeq(StringPiece line, StringPiece directive) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900372 IfStmt* stmt = new IfStmt();
373 stmt->set_loc(loc_);
374 stmt->op = directive[2] == 'n' ? CondOp::IFNEQ : CondOp::IFEQ;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900375
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900376 if (!ParseIfEqCond(line, stmt)) {
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900377 Error("*** invalid syntax in conditional.");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900378 return;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900379 }
380
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900381 out_stmts_->push_back(stmt);
382 EnterIf(stmt);
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900383 }
384
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900385 void ParseElse(StringPiece line, StringPiece) {
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900386 if (!CheckIfStack("else"))
387 return;
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900388 IfState* st = if_stack_.top();
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900389 if (st->is_in_else) {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900390 Error("*** only one `else' per conditional.");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900391 return;
392 }
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900393 st->is_in_else = true;
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900394 out_stmts_ = &st->stmt->false_stmts;
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900395
396 StringPiece next_if = TrimLeftSpace(line);
397 if (next_if.empty())
398 return;
399
400 num_if_nest_ = st->num_nest + 1;
401 if (!HandleDirective(next_if, else_if_directives_)) {
402 WARN("%s:%d: extraneous text after `else' directive", LOCF(loc_));
403 }
404 num_if_nest_ = 0;
405 }
406
407 void ParseEndif(StringPiece line, StringPiece) {
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900408 if (!CheckIfStack("endif"))
409 return;
410 if (!line.empty()) {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900411 Error("extraneous text after `endif` directive");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900412 return;
413 }
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900414 IfState st = *if_stack_.top();
415 for (int t = 0; t <= st.num_nest; t++) {
416 delete if_stack_.top();
417 if_stack_.pop();
418 if (if_stack_.empty()) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900419 out_stmts_ = stmts_;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900420 } else {
421 IfState* st = if_stack_.top();
422 if (st->is_in_else)
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900423 out_stmts_ = &st->stmt->false_stmts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900424 else
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900425 out_stmts_ = &st->stmt->true_stmts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900426 }
427 }
428 }
429
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900430 bool IsInExport() const {
431 return (static_cast<int>(current_directive_) &
432 static_cast<int>(AssignDirective::EXPORT));
433 }
434
435 void CreateExport(StringPiece line, bool is_export) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900436 ExportStmt* stmt = new ExportStmt;
437 stmt->set_loc(loc_);
438 stmt->expr = ParseExpr(line);
439 stmt->is_export = is_export;
440 out_stmts_->push_back(stmt);
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900441 }
442
443 void ParseOverride(StringPiece line, StringPiece) {
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900444 current_directive_ =
445 static_cast<AssignDirective>(
446 (static_cast<int>(current_directive_) |
447 static_cast<int>(AssignDirective::OVERRIDE)));
448 if (HandleDirective(line, assign_directives_))
449 return;
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900450 if (IsInExport()) {
451 CreateExport(line, true);
452 }
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900453 ParseRuleOrAssign(line);
454 }
455
456 void ParseExport(StringPiece line, StringPiece) {
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900457 current_directive_ =
458 static_cast<AssignDirective>(
459 (static_cast<int>(current_directive_) |
460 static_cast<int>(AssignDirective::EXPORT)));
461 if (HandleDirective(line, assign_directives_))
462 return;
463 CreateExport(line, true);
464 ParseRuleOrAssign(line);
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900465 }
466
467 void ParseUnexport(StringPiece line, StringPiece) {
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900468 CreateExport(line, false);
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900469 }
470
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900471 bool CheckIfStack(const char* keyword) {
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900472 if (if_stack_.empty()) {
473 Error(StringPrintf("*** extraneous `%s'.", keyword));
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900474 return false;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900475 }
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900476 return true;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900477 }
478
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900479 StringPiece RemoveComment(StringPiece line) {
Shinichiro Hamajieafd0522015-06-18 16:46:02 +0900480 size_t i = FindOutsideParen(line, '#');
481 if (i == string::npos)
482 return line;
483 return line.substr(0, i);
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900484 }
485
486 StringPiece GetDirective(StringPiece line) {
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900487 if (line.size() < shortest_directive_len_)
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900488 return StringPiece();
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900489 StringPiece prefix = line.substr(0, longest_directive_len_ + 1);
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900490 size_t space_index = prefix.find_first_of(" \t#");
491 return prefix.substr(0, space_index);
492 }
493
494 bool HandleDirective(StringPiece line, const DirectiveMap* directive_map) {
495 StringPiece directive = GetDirective(line);
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900496 auto found = directive_map->find(directive);
497 if (found == directive_map->end())
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900498 return false;
499
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900500 StringPiece rest = TrimRightSpace(RemoveComment(TrimLeftSpace(
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900501 line.substr(directive.size()))));
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900502 (this->*found->second)(rest, directive);
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900503 return true;
504 }
505
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900506 StringPiece buf_;
507 size_t l_;
508 ParserState state_;
509
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900510 vector<Stmt*>* stmts_;
511 vector<Stmt*>* out_stmts_;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900512
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900513 StringPiece define_name_;
514 size_t define_start_;
515 int define_start_line_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900516
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900517 StringPiece orig_line_with_directives_;
518 AssignDirective current_directive_;
519
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900520 int num_if_nest_;
521 stack<IfState*> if_stack_;
522
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900523 Loc loc_;
524 bool fixed_lineno_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900525
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900526 static DirectiveMap* make_directives_;
527 static DirectiveMap* else_if_directives_;
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900528 static DirectiveMap* assign_directives_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900529 static size_t shortest_directive_len_;
530 static size_t longest_directive_len_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900531};
532
533void Parse(Makefile* mk) {
Shinichiro Hamaji6b1a11a2015-06-30 16:21:19 +0900534 COLLECT_STATS("parse file time");
Shinichiro Hamaji07550472016-02-29 19:56:50 +0900535 Parser parser(StringPiece(mk->buf()),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900536 mk->filename().c_str(),
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900537 mk->mutable_stmts());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900538 parser.Parse();
539}
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900540
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900541void Parse(StringPiece buf, const Loc& loc, vector<Stmt*>* out_stmts) {
Shinichiro Hamaji6b1a11a2015-06-30 16:21:19 +0900542 COLLECT_STATS("parse eval time");
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900543 Parser parser(buf, loc, out_stmts);
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900544 parser.Parse();
545}
546
Shinichiro Hamaji631a9f82015-07-05 14:18:15 +0900547void ParseNotAfterRule(StringPiece buf, const Loc& loc,
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900548 vector<Stmt*>* out_stmts) {
549 Parser parser(buf, loc, out_stmts);
Shinichiro Hamaji631a9f82015-07-05 14:18:15 +0900550 parser.set_state(ParserState::NOT_AFTER_RULE);
551 parser.Parse();
552}
553
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900554void InitParser() {
555 Parser::Init();
556}
557
558void QuitParser() {
559 Parser::Quit();
560}
561
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900562Parser::DirectiveMap* Parser::make_directives_;
563Parser::DirectiveMap* Parser::else_if_directives_;
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900564Parser::DirectiveMap* Parser::assign_directives_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900565size_t Parser::shortest_directive_len_;
566size_t Parser::longest_directive_len_;
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900567vector<ParseErrorStmt*> Parser::parse_errors;
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900568
569void ParseAssignStatement(StringPiece line, size_t sep,
570 StringPiece* lhs, StringPiece* rhs, AssignOp* op) {
571 CHECK(sep != 0);
572 *op = AssignOp::EQ;
573 size_t lhs_end = sep;
574 switch (line[sep-1]) {
575 case ':':
576 lhs_end--;
577 *op = AssignOp::COLON_EQ;
578 break;
579 case '+':
580 lhs_end--;
581 *op = AssignOp::PLUS_EQ;
582 break;
583 case '?':
584 lhs_end--;
585 *op = AssignOp::QUESTION_EQ;
586 break;
587 }
588 *lhs = TrimSpace(line.substr(0, lhs_end));
Shinichiro Hamaji748969f2015-10-27 10:10:26 +0900589 *rhs = TrimLeftSpace(line.substr(sep + 1));
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900590}
Shinichiro Hamajia06bee92015-08-05 17:13:05 +0900591
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900592const vector<ParseErrorStmt*>& GetParseErrors() {
Shinichiro Hamajia06bee92015-08-05 17:13:05 +0900593 return Parser::parse_errors;
594}