blob: 050f35dd54df3b2c632892978c7379b3b0610441 [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
Dan Willemsen3ce083f2017-10-11 22:17:48 -070044 typedef void (Parser::*DirectiveHandler)(StringPiece line,
45 StringPiece directive);
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +090046 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 Hamaji390115c2016-05-30 18:41:21 +090054 num_define_nest_(0),
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090055 num_if_nest_(0),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090056 loc_(filename, 0),
Dan Willemsen3ce083f2017-10-11 22:17:48 -070057 fixed_lineno_(false) {}
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090058
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),
Dan Willemsen3ce083f2017-10-11 22:17:48 -070066 fixed_lineno_(true) {}
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +090067
Dan Willemsen3ce083f2017-10-11 22:17:48 -070068 ~Parser() {}
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090069
70 void Parse() {
71 l_ = 0;
72
73 for (l_ = 0; l_ < buf_.size();) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090074 size_t lf_cnt = 0;
75 size_t e = FindEndOfLine(&lf_cnt);
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +090076 if (!fixed_lineno_)
Shinichiro Hamajib3af68b2015-06-24 20:47:57 +090077 loc_.lineno++;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090078 StringPiece line(buf_.data() + l_, e - l_);
Shinichiro Hamajibecba502016-04-12 15:21:08 +090079 if (line.get(line.size() - 1) == '\r')
80 line.remove_suffix(1);
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())
Dan Willemsene41c7552017-02-22 14:31:16 -080092 ERROR_LOC(Loc(loc_.filename, loc_.lineno + 1), "*** missing `endif'.");
Shinichiro Hamaji89f6a2b2016-04-09 12:32:23 +090093 if (!define_name_.empty())
Dan Willemsene41c7552017-02-22 14:31:16 -080094 ERROR_LOC(Loc(loc_.filename, define_start_line_),
95 "*** missing `endef', unterminated `define'.");
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090096 }
97
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +090098 static void Init() {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +090099 make_directives_ = new DirectiveMap;
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900100 (*make_directives_)["include"] = &Parser::ParseInclude;
101 (*make_directives_)["-include"] = &Parser::ParseInclude;
102 (*make_directives_)["sinclude"] = &Parser::ParseInclude;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900103 (*make_directives_)["define"] = &Parser::ParseDefine;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900104 (*make_directives_)["ifdef"] = &Parser::ParseIfdef;
105 (*make_directives_)["ifndef"] = &Parser::ParseIfdef;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900106 (*make_directives_)["ifeq"] = &Parser::ParseIfeq;
107 (*make_directives_)["ifneq"] = &Parser::ParseIfeq;
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900108 (*make_directives_)["else"] = &Parser::ParseElse;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900109 (*make_directives_)["endif"] = &Parser::ParseEndif;
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900110 (*make_directives_)["override"] = &Parser::ParseOverride;
111 (*make_directives_)["export"] = &Parser::ParseExport;
112 (*make_directives_)["unexport"] = &Parser::ParseUnexport;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900113
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900114 else_if_directives_ = new DirectiveMap;
115 (*else_if_directives_)["ifdef"] = &Parser::ParseIfdef;
116 (*else_if_directives_)["ifndef"] = &Parser::ParseIfdef;
Shinichiro Hamaji6aeab2a2015-06-26 09:12:01 +0900117 (*else_if_directives_)["ifeq"] = &Parser::ParseIfeq;
118 (*else_if_directives_)["ifneq"] = &Parser::ParseIfeq;
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900119
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900120 assign_directives_ = new DirectiveMap;
121 (*assign_directives_)["define"] = &Parser::ParseDefine;
122 (*assign_directives_)["export"] = &Parser::ParseExport;
123 (*assign_directives_)["override"] = &Parser::ParseOverride;
124
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900125 shortest_directive_len_ = 9999;
126 longest_directive_len_ = 0;
127 for (auto p : *make_directives_) {
128 size_t len = p.first.size();
129 shortest_directive_len_ = min(len, shortest_directive_len_);
130 longest_directive_len_ = max(len, longest_directive_len_);
131 }
132 }
133
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700134 static void Quit() { delete make_directives_; }
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900135
Shinichiro Hamaji631a9f82015-07-05 14:18:15 +0900136 void set_state(ParserState st) { state_ = st; }
137
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900138 static vector<ParseErrorStmt*> parse_errors;
Shinichiro Hamajia06bee92015-08-05 17:13:05 +0900139
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900140 private:
141 void Error(const string& msg) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900142 ParseErrorStmt* stmt = new ParseErrorStmt();
143 stmt->set_loc(loc_);
144 stmt->msg = msg;
145 out_stmts_->push_back(stmt);
146 parse_errors.push_back(stmt);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900147 }
148
149 size_t FindEndOfLine(size_t* lf_cnt) {
Shinichiro Hamaji14bb2792015-06-25 18:24:11 +0900150 return ::FindEndOfLine(buf_, l_, lf_cnt);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900151 }
152
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900153 Value* ParseExpr(StringPiece s, ParseExprOpt opt = ParseExprOpt::NORMAL) {
154 return ::ParseExpr(loc_, s, opt);
155 }
156
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900157 void ParseLine(StringPiece line) {
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900158 if (!define_name_.empty()) {
159 ParseInsideDefine(line);
160 return;
161 }
162
Shinichiro Hamajic6ac0b92015-07-06 16:24:10 +0900163 if (line.empty() || (line.size() == 1 && line[0] == '\r'))
164 return;
165
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900166 current_directive_ = AssignDirective::NONE;
167
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900168 if (line[0] == '\t' && state_ != ParserState::NOT_AFTER_RULE) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900169 CommandStmt* stmt = new CommandStmt();
170 stmt->set_loc(loc_);
171 stmt->expr = ParseExpr(line.substr(1), ParseExprOpt::COMMAND);
172 stmt->orig = line;
173 out_stmts_->push_back(stmt);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900174 return;
175 }
176
Shinichiro Hamaji32750622015-06-17 14:57:33 +0900177 line = TrimLeftSpace(line);
Shinichiro Hamajid4e81932015-06-17 04:40:45 +0900178
179 if (line[0] == '#')
180 return;
181
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900182 if (HandleDirective(line, make_directives_)) {
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900183 return;
184 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900185
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900186 ParseRuleOrAssign(line);
187 }
188
189 void ParseRuleOrAssign(StringPiece line) {
Shinichiro Hamaji415a9b12015-07-05 14:33:02 +0900190 size_t sep = FindThreeOutsideParen(line, ':', '=', ';');
191 if (sep == string::npos || line[sep] == ';') {
192 ParseRule(line, string::npos);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900193 } else if (line[sep] == '=') {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900194 ParseAssign(line, sep);
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700195 } else if (line.get(sep + 1) == '=') {
196 ParseAssign(line, sep + 1);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900197 } else if (line[sep] == ':') {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900198 ParseRule(line, sep);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900199 } else {
200 CHECK(false);
201 }
202 }
203
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900204 void ParseRule(StringPiece line, size_t sep) {
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900205 if (current_directive_ != AssignDirective::NONE) {
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900206 if (IsInExport())
207 return;
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900208 if (sep != string::npos) {
209 sep += orig_line_with_directives_.size() - line.size();
210 }
211 line = orig_line_with_directives_;
Shinichiro Hamajidf066c32015-06-26 09:09:26 +0900212 }
213
Shinichiro Hamaji6aeab2a2015-06-26 09:12:01 +0900214 line = TrimLeftSpace(line);
Shinichiro Hamajidf066c32015-06-26 09:09:26 +0900215 if (line.empty())
216 return;
217
218 if (orig_line_with_directives_[0] == '\t') {
Shinichiro Hamaji2bed7702015-06-26 07:56:28 +0900219 Error("*** commands commence before first target.");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900220 return;
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900221 }
222
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900223 const bool is_rule = sep != string::npos && line[sep] == ':';
Sasha Smundakce812f52018-08-15 14:49:39 -0700224 RuleStmt* rule_stmt = new RuleStmt();
225 rule_stmt->set_loc(loc_);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900226
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900227 size_t found = FindTwoOutsideParen(line.substr(sep + 1), '=', ';');
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900228 if (found != string::npos) {
229 found += sep + 1;
Sasha Smundakce812f52018-08-15 14:49:39 -0700230 rule_stmt->lhs = ParseExpr(TrimSpace(line.substr(0, found)));
231 if (line[found] == ';') {
232 rule_stmt->sep = RuleStmt::SEP_SEMICOLON;
233 } else if (line[found] == '=') {
234 if (line.size() > (found + 2) && line[found + 1] == '$' && line[found + 2] == '=') {
235 rule_stmt->sep = RuleStmt::SEP_FINALEQ;
236 found += 2;
237 } else {
238 rule_stmt->sep = RuleStmt::SEP_EQ;
239 }
240 }
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900241 ParseExprOpt opt =
Sasha Smundakce812f52018-08-15 14:49:39 -0700242 rule_stmt->sep == RuleStmt::SEP_SEMICOLON ? ParseExprOpt::COMMAND : ParseExprOpt::NORMAL;
243 rule_stmt->rhs = ParseExpr(TrimLeftSpace(line.substr(found + 1)), opt);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900244 } else {
Sasha Smundakce812f52018-08-15 14:49:39 -0700245 rule_stmt->lhs = ParseExpr(line);
246 rule_stmt->sep = RuleStmt::SEP_NULL;
247 rule_stmt->rhs = NULL;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900248 }
Sasha Smundakce812f52018-08-15 14:49:39 -0700249 out_stmts_->push_back(rule_stmt);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900250 state_ = is_rule ? ParserState::AFTER_RULE : ParserState::MAYBE_AFTER_RULE;
251 }
252
Sasha Smundakce812f52018-08-15 14:49:39 -0700253 void ParseAssign(StringPiece line, size_t separator_pos) {
254 if (separator_pos == 0) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900255 Error("*** empty variable name ***");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900256 return;
257 }
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900258 StringPiece lhs;
259 StringPiece rhs;
260 AssignOp op;
Sasha Smundakce812f52018-08-15 14:49:39 -0700261 ParseAssignStatement(line, separator_pos, &lhs, &rhs, &op);
262
263 // If rhs starts with '$=', this is 'final assignment',
264 // e.g., a combination of the assignment and
265 // .KATI_READONLY := <lhs>
266 // statement. Note that we assume that ParseAssignStatement
267 // trimmed the left
268 bool is_final = (rhs.size() >= 2 && rhs[0] == '$' && rhs[1] == '=');
269 if (is_final) {
270 rhs = TrimLeftSpace(rhs.substr(2));
271 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900272
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900273 AssignStmt* stmt = new AssignStmt();
274 stmt->set_loc(loc_);
275 stmt->lhs = ParseExpr(lhs);
276 stmt->rhs = ParseExpr(rhs);
277 stmt->orig_rhs = rhs;
278 stmt->op = op;
279 stmt->directive = current_directive_;
Sasha Smundakce812f52018-08-15 14:49:39 -0700280 stmt->is_final = is_final;
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900281 out_stmts_->push_back(stmt);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900282 state_ = ParserState::NOT_AFTER_RULE;
283 }
284
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900285 void ParseInclude(StringPiece line, StringPiece directive) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900286 IncludeStmt* stmt = new IncludeStmt();
287 stmt->set_loc(loc_);
288 stmt->expr = ParseExpr(line);
289 stmt->should_exist = directive[0] == 'i';
290 out_stmts_->push_back(stmt);
Shinichiro Hamajiff4584d2015-06-24 17:45:14 +0900291 state_ = ParserState::NOT_AFTER_RULE;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900292 }
293
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900294 void ParseDefine(StringPiece line, StringPiece) {
295 if (line.empty()) {
296 Error("*** empty variable name.");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900297 return;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900298 }
299 define_name_ = line;
Shinichiro Hamaji390115c2016-05-30 18:41:21 +0900300 num_define_nest_ = 1;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900301 define_start_ = 0;
302 define_start_line_ = loc_.lineno;
Shinichiro Hamajiff4584d2015-06-24 17:45:14 +0900303 state_ = ParserState::NOT_AFTER_RULE;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900304 }
305
306 void ParseInsideDefine(StringPiece line) {
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900307 line = TrimLeftSpace(line);
Shinichiro Hamaji390115c2016-05-30 18:41:21 +0900308 StringPiece directive = GetDirective(line);
309 if (directive == "define")
310 num_define_nest_++;
311 else if (directive == "endef")
312 num_define_nest_--;
313 if (num_define_nest_ > 0) {
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900314 if (define_start_ == 0)
315 define_start_ = l_;
316 return;
317 }
318
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700319 StringPiece rest = TrimRightSpace(
320 RemoveComment(TrimLeftSpace(line.substr(sizeof("endef")))));
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900321 if (!rest.empty()) {
Dan Willemsene41c7552017-02-22 14:31:16 -0800322 WARN_LOC(loc_, "extraneous text after `endef' directive");
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900323 }
324
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900325 AssignStmt* stmt = new AssignStmt();
326 stmt->set_loc(Loc(loc_.filename, define_start_line_));
327 stmt->lhs = ParseExpr(define_name_);
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900328 StringPiece rhs;
329 if (define_start_)
Shinichiro Hamajia4d0ecb2015-06-24 22:08:30 +0900330 rhs = buf_.substr(define_start_, l_ - define_start_ - 1);
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900331 stmt->rhs = ParseExpr(rhs, ParseExprOpt::DEFINE);
332 stmt->orig_rhs = rhs;
333 stmt->op = AssignOp::EQ;
334 stmt->directive = current_directive_;
335 out_stmts_->push_back(stmt);
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900336 define_name_.clear();
337 }
338
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900339 void EnterIf(IfStmt* stmt) {
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900340 IfState* st = new IfState();
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900341 st->stmt = stmt;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900342 st->is_in_else = false;
343 st->num_nest = num_if_nest_;
344 if_stack_.push(st);
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900345 out_stmts_ = &stmt->true_stmts;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900346 }
347
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900348 void ParseIfdef(StringPiece line, StringPiece directive) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900349 IfStmt* stmt = new IfStmt();
350 stmt->set_loc(loc_);
351 stmt->op = directive[2] == 'n' ? CondOp::IFNDEF : CondOp::IFDEF;
352 stmt->lhs = ParseExpr(line);
353 stmt->rhs = NULL;
354 out_stmts_->push_back(stmt);
355 EnterIf(stmt);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900356 }
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900357
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900358 bool ParseIfEqCond(StringPiece s, IfStmt* stmt) {
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900359 if (s.empty()) {
360 return false;
361 }
362
363 if (s[0] == '(' && s[s.size() - 1] == ')') {
364 s = s.substr(1, s.size() - 2);
365 char terms[] = {',', '\0'};
366 size_t n;
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900367 stmt->lhs = ParseExprImpl(loc_, s, terms, ParseExprOpt::NORMAL, &n, true);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900368 if (s[n] != ',')
369 return false;
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700370 s = TrimLeftSpace(s.substr(n + 1));
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900371 stmt->rhs = ParseExprImpl(loc_, s, NULL, ParseExprOpt::NORMAL, &n);
Shinichiro Hamajiadeea692015-06-17 17:57:31 +0900372 s = TrimLeftSpace(s.substr(n));
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900373 } else {
374 for (int i = 0; i < 2; i++) {
375 if (s.empty())
376 return false;
377 char quote = s[0];
378 if (quote != '\'' && quote != '"')
379 return false;
380 size_t end = s.find(quote, 1);
381 if (end == string::npos)
382 return false;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900383 Value* v = ParseExpr(s.substr(1, end - 1), ParseExprOpt::NORMAL);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900384 if (i == 0)
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900385 stmt->lhs = v;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900386 else
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900387 stmt->rhs = v;
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700388 s = TrimLeftSpace(s.substr(end + 1));
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900389 }
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900390 }
Shinichiro Hamajiadeea692015-06-17 17:57:31 +0900391 if (!s.empty()) {
Dan Willemsene41c7552017-02-22 14:31:16 -0800392 WARN_LOC(loc_, "extraneous text after `ifeq' directive");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900393 return true;
Shinichiro Hamajiadeea692015-06-17 17:57:31 +0900394 }
395 return true;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900396 }
397
398 void ParseIfeq(StringPiece line, StringPiece directive) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900399 IfStmt* stmt = new IfStmt();
400 stmt->set_loc(loc_);
401 stmt->op = directive[2] == 'n' ? CondOp::IFNEQ : CondOp::IFEQ;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900402
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900403 if (!ParseIfEqCond(line, stmt)) {
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900404 Error("*** invalid syntax in conditional.");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900405 return;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900406 }
407
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900408 out_stmts_->push_back(stmt);
409 EnterIf(stmt);
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900410 }
411
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900412 void ParseElse(StringPiece line, StringPiece) {
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900413 if (!CheckIfStack("else"))
414 return;
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900415 IfState* st = if_stack_.top();
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900416 if (st->is_in_else) {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900417 Error("*** only one `else' per conditional.");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900418 return;
419 }
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900420 st->is_in_else = true;
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900421 out_stmts_ = &st->stmt->false_stmts;
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900422
423 StringPiece next_if = TrimLeftSpace(line);
424 if (next_if.empty())
425 return;
426
427 num_if_nest_ = st->num_nest + 1;
428 if (!HandleDirective(next_if, else_if_directives_)) {
Dan Willemsene41c7552017-02-22 14:31:16 -0800429 WARN_LOC(loc_, "extraneous text after `else' directive");
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900430 }
431 num_if_nest_ = 0;
432 }
433
434 void ParseEndif(StringPiece line, StringPiece) {
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900435 if (!CheckIfStack("endif"))
436 return;
437 if (!line.empty()) {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900438 Error("extraneous text after `endif` directive");
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900439 return;
440 }
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900441 IfState st = *if_stack_.top();
442 for (int t = 0; t <= st.num_nest; t++) {
443 delete if_stack_.top();
444 if_stack_.pop();
445 if (if_stack_.empty()) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900446 out_stmts_ = stmts_;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900447 } else {
448 IfState* st = if_stack_.top();
449 if (st->is_in_else)
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900450 out_stmts_ = &st->stmt->false_stmts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900451 else
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900452 out_stmts_ = &st->stmt->true_stmts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900453 }
454 }
455 }
456
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900457 bool IsInExport() const {
458 return (static_cast<int>(current_directive_) &
459 static_cast<int>(AssignDirective::EXPORT));
460 }
461
462 void CreateExport(StringPiece line, bool is_export) {
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900463 ExportStmt* stmt = new ExportStmt;
464 stmt->set_loc(loc_);
465 stmt->expr = ParseExpr(line);
466 stmt->is_export = is_export;
467 out_stmts_->push_back(stmt);
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900468 }
469
470 void ParseOverride(StringPiece line, StringPiece) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700471 current_directive_ = static_cast<AssignDirective>(
472 (static_cast<int>(current_directive_) |
473 static_cast<int>(AssignDirective::OVERRIDE)));
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900474 if (HandleDirective(line, assign_directives_))
475 return;
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900476 if (IsInExport()) {
477 CreateExport(line, true);
478 }
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900479 ParseRuleOrAssign(line);
480 }
481
482 void ParseExport(StringPiece line, StringPiece) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700483 current_directive_ = static_cast<AssignDirective>(
484 (static_cast<int>(current_directive_) |
485 static_cast<int>(AssignDirective::EXPORT)));
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900486 if (HandleDirective(line, assign_directives_))
487 return;
488 CreateExport(line, true);
489 ParseRuleOrAssign(line);
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900490 }
491
492 void ParseUnexport(StringPiece line, StringPiece) {
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900493 CreateExport(line, false);
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900494 }
495
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900496 bool CheckIfStack(const char* keyword) {
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900497 if (if_stack_.empty()) {
498 Error(StringPrintf("*** extraneous `%s'.", keyword));
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900499 return false;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900500 }
Shinichiro Hamaji56227862015-08-05 16:53:37 +0900501 return true;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900502 }
503
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900504 StringPiece RemoveComment(StringPiece line) {
Shinichiro Hamajieafd0522015-06-18 16:46:02 +0900505 size_t i = FindOutsideParen(line, '#');
506 if (i == string::npos)
507 return line;
508 return line.substr(0, i);
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900509 }
510
511 StringPiece GetDirective(StringPiece line) {
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900512 if (line.size() < shortest_directive_len_)
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900513 return StringPiece();
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900514 StringPiece prefix = line.substr(0, longest_directive_len_ + 1);
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900515 size_t space_index = prefix.find_first_of(" \t#");
516 return prefix.substr(0, space_index);
517 }
518
519 bool HandleDirective(StringPiece line, const DirectiveMap* directive_map) {
520 StringPiece directive = GetDirective(line);
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900521 auto found = directive_map->find(directive);
522 if (found == directive_map->end())
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900523 return false;
524
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700525 StringPiece rest = TrimRightSpace(
526 RemoveComment(TrimLeftSpace(line.substr(directive.size()))));
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900527 (this->*found->second)(rest, directive);
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900528 return true;
529 }
530
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900531 StringPiece buf_;
532 size_t l_;
533 ParserState state_;
534
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900535 vector<Stmt*>* stmts_;
536 vector<Stmt*>* out_stmts_;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900537
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900538 StringPiece define_name_;
Shinichiro Hamaji390115c2016-05-30 18:41:21 +0900539 int num_define_nest_;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900540 size_t define_start_;
541 int define_start_line_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900542
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900543 StringPiece orig_line_with_directives_;
544 AssignDirective current_directive_;
545
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900546 int num_if_nest_;
547 stack<IfState*> if_stack_;
548
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900549 Loc loc_;
550 bool fixed_lineno_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900551
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900552 static DirectiveMap* make_directives_;
553 static DirectiveMap* else_if_directives_;
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900554 static DirectiveMap* assign_directives_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900555 static size_t shortest_directive_len_;
556 static size_t longest_directive_len_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900557};
558
559void Parse(Makefile* mk) {
Shinichiro Hamaji6b1a11a2015-06-30 16:21:19 +0900560 COLLECT_STATS("parse file time");
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700561 Parser parser(StringPiece(mk->buf()), mk->filename().c_str(),
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900562 mk->mutable_stmts());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900563 parser.Parse();
564}
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900565
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900566void Parse(StringPiece buf, const Loc& loc, vector<Stmt*>* out_stmts) {
Shinichiro Hamaji6b1a11a2015-06-30 16:21:19 +0900567 COLLECT_STATS("parse eval time");
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900568 Parser parser(buf, loc, out_stmts);
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900569 parser.Parse();
570}
571
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700572void ParseNotAfterRule(StringPiece buf,
573 const Loc& loc,
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900574 vector<Stmt*>* out_stmts) {
575 Parser parser(buf, loc, out_stmts);
Shinichiro Hamaji631a9f82015-07-05 14:18:15 +0900576 parser.set_state(ParserState::NOT_AFTER_RULE);
577 parser.Parse();
578}
579
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900580void InitParser() {
581 Parser::Init();
582}
583
584void QuitParser() {
585 Parser::Quit();
586}
587
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900588Parser::DirectiveMap* Parser::make_directives_;
589Parser::DirectiveMap* Parser::else_if_directives_;
Shinichiro Hamaji420f7752015-06-26 04:02:02 +0900590Parser::DirectiveMap* Parser::assign_directives_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900591size_t Parser::shortest_directive_len_;
592size_t Parser::longest_directive_len_;
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900593vector<ParseErrorStmt*> Parser::parse_errors;
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900594
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700595void ParseAssignStatement(StringPiece line,
596 size_t sep,
597 StringPiece* lhs,
598 StringPiece* rhs,
599 AssignOp* op) {
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900600 CHECK(sep != 0);
601 *op = AssignOp::EQ;
602 size_t lhs_end = sep;
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700603 switch (line[sep - 1]) {
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900604 case ':':
605 lhs_end--;
606 *op = AssignOp::COLON_EQ;
607 break;
608 case '+':
609 lhs_end--;
610 *op = AssignOp::PLUS_EQ;
611 break;
612 case '?':
613 lhs_end--;
614 *op = AssignOp::QUESTION_EQ;
615 break;
616 }
617 *lhs = TrimSpace(line.substr(0, lhs_end));
Shinichiro Hamaji748969f2015-10-27 10:10:26 +0900618 *rhs = TrimLeftSpace(line.substr(sep + 1));
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900619}
Shinichiro Hamajia06bee92015-08-05 17:13:05 +0900620
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900621const vector<ParseErrorStmt*>& GetParseErrors() {
Shinichiro Hamajia06bee92015-08-05 17:13:05 +0900622 return Parser::parse_errors;
623}