blob: aca28b6a5d6e37e4f0b9d7a4f62e75b30c2a6999 [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
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090015#include "parser.h"
16
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090017#include <stack>
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +090018#include <unordered_map>
19
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090020#include "ast.h"
21#include "file.h"
22#include "loc.h"
23#include "log.h"
24#include "string_piece.h"
Shinichiro Hamaji810fd032015-06-17 04:38:03 +090025#include "strutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090026#include "value.h"
27
28enum struct ParserState {
29 NOT_AFTER_RULE = 0,
30 AFTER_RULE,
31 MAYBE_AFTER_RULE,
32};
33
34class Parser {
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090035 struct IfState {
36 IfAST* ast;
37 bool is_in_else;
38 int num_nest;
39 };
40
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +090041 typedef void (Parser::*DirectiveHandler)(
42 StringPiece line, StringPiece directive);
43 typedef unordered_map<StringPiece, DirectiveHandler> DirectiveMap;
44
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090045 public:
46 Parser(StringPiece buf, const char* filename, vector<AST*>* asts)
47 : buf_(buf),
48 state_(ParserState::NOT_AFTER_RULE),
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090049 asts_(asts),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090050 out_asts_(asts),
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090051 num_if_nest_(0),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090052 loc_(filename, 0),
53 fixed_lineno_(false) {
54 }
55
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +090056 Parser(StringPiece buf, const Loc& loc, vector<AST*>* asts)
57 : buf_(buf),
58 state_(ParserState::NOT_AFTER_RULE),
59 asts_(asts),
60 out_asts_(asts),
61 num_if_nest_(0),
62 loc_(loc),
63 fixed_lineno_(true) {
64 }
65
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090066 ~Parser() {
67 }
68
69 void Parse() {
70 l_ = 0;
71
72 for (l_ = 0; l_ < buf_.size();) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090073 size_t lf_cnt = 0;
74 size_t e = FindEndOfLine(&lf_cnt);
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +090075 if (!fixed_lineno_)
76 loc_.lineno += lf_cnt;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090077 StringPiece line(buf_.data() + l_, e - l_);
78 ParseLine(line);
79 if (e == buf_.size())
80 break;
81
82 l_ = e + 1;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090083 }
84 }
85
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +090086 static void Init() {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +090087 make_directives_ = new DirectiveMap;
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +090088 (*make_directives_)["include"] = &Parser::ParseInclude;
89 (*make_directives_)["-include"] = &Parser::ParseInclude;
90 (*make_directives_)["sinclude"] = &Parser::ParseInclude;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +090091 (*make_directives_)["define"] = &Parser::ParseDefine;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090092 (*make_directives_)["ifdef"] = &Parser::ParseIfdef;
93 (*make_directives_)["ifndef"] = &Parser::ParseIfdef;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +090094 (*make_directives_)["ifeq"] = &Parser::ParseIfeq;
95 (*make_directives_)["ifneq"] = &Parser::ParseIfeq;
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +090096 (*make_directives_)["else"] = &Parser::ParseElse;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090097 (*make_directives_)["endif"] = &Parser::ParseEndif;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +090098
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +090099 else_if_directives_ = new DirectiveMap;
100 (*else_if_directives_)["ifdef"] = &Parser::ParseIfdef;
101 (*else_if_directives_)["ifndef"] = &Parser::ParseIfdef;
102
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900103 shortest_directive_len_ = 9999;
104 longest_directive_len_ = 0;
105 for (auto p : *make_directives_) {
106 size_t len = p.first.size();
107 shortest_directive_len_ = min(len, shortest_directive_len_);
108 longest_directive_len_ = max(len, longest_directive_len_);
109 }
110 }
111
112 static void Quit() {
113 delete make_directives_;
114 }
115
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900116 private:
117 void Error(const string& msg) {
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +0900118 ERROR("%s:%d: %s", LOCF(loc_), msg.c_str());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900119 }
120
121 size_t FindEndOfLine(size_t* lf_cnt) {
122 size_t e = l_;
123 bool prev_backslash = false;
124 for (; e < buf_.size(); e++) {
125 char c = buf_[e];
126 if (c == '\\') {
127 prev_backslash = !prev_backslash;
128 } else if (c == '\n') {
129 ++*lf_cnt;
130 if (!prev_backslash) {
131 return e;
132 }
133 } else if (c != '\r') {
134 prev_backslash = false;
135 }
136 }
137 return e;
138 }
139
140 void ParseLine(StringPiece line) {
141 if (line.empty() || (line.size() == 1 && line[0] == '\r'))
142 return;
143
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900144 if (!define_name_.empty()) {
145 ParseInsideDefine(line);
146 return;
147 }
148
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900149 if (line[0] == '\t' && state_ != ParserState::NOT_AFTER_RULE) {
150 CommandAST* ast = new CommandAST();
Shinichiro Hamaji861bd642015-06-19 16:59:13 +0900151 ast->set_loc(loc_);
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900152 ast->expr = ParseExpr(line.substr(1), ParseExprOpt::COMMAND);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900153 out_asts_->push_back(ast);
154 return;
155 }
156
Shinichiro Hamaji32750622015-06-17 14:57:33 +0900157 line = TrimLeftSpace(line);
Shinichiro Hamajid4e81932015-06-17 04:40:45 +0900158
159 if (line[0] == '#')
160 return;
161
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900162 if (HandleDirective(line, make_directives_)) {
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900163 return;
164 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900165
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900166 size_t sep = FindTwoOutsideParen(line, ':', '=');
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900167 if (sep == string::npos) {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900168 ParseRule(line, sep);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900169 } else if (line[sep] == '=') {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900170 ParseAssign(line, sep);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900171 } else if (line.get(sep+1) == '=') {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900172 ParseAssign(line, sep+1);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900173 } else if (line[sep] == ':') {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900174 ParseRule(line, sep);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900175 } else {
176 CHECK(false);
177 }
178 }
179
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900180 void ParseRule(StringPiece line, size_t sep) {
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900181 const bool is_rule = sep != string::npos && line[sep] == ':';
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900182 RuleAST* ast = new RuleAST();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900183 ast->set_loc(loc_);
184
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900185 size_t found = FindTwoOutsideParen(line.substr(sep + 1), '=', ';');
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900186 if (found != string::npos) {
187 found += sep + 1;
188 ast->term = line[found];
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900189 ParseExprOpt opt =
190 ast->term == ';' ? ParseExprOpt::COMMAND : ParseExprOpt::NORMAL;
191 ast->after_term = ParseExpr(TrimLeftSpace(line.substr(found + 1)), opt);
192 ast->expr = ParseExpr(TrimSpace(line.substr(0, found)));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900193 } else {
194 ast->term = 0;
195 ast->after_term = NULL;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900196 ast->expr = ParseExpr(TrimSpace(line));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900197 }
198 out_asts_->push_back(ast);
199 state_ = is_rule ? ParserState::AFTER_RULE : ParserState::MAYBE_AFTER_RULE;
200 }
201
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900202 void ParseAssign(StringPiece line, size_t sep) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900203 if (sep == 0)
204 Error("*** empty variable name ***");
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900205 StringPiece lhs;
206 StringPiece rhs;
207 AssignOp op;
208 ParseAssignStatement(line, sep, &lhs, &rhs, &op);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900209
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900210 AssignAST* ast = new AssignAST();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900211 ast->set_loc(loc_);
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900212 ast->lhs = ParseExpr(lhs);
213 ast->rhs = ParseExpr(rhs);
Shinichiro Hamaji81699be2015-06-22 18:07:38 +0900214 ast->orig_rhs = rhs;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900215 ast->op = op;
216 ast->directive = AssignDirective::NONE;
217 out_asts_->push_back(ast);
218 state_ = ParserState::NOT_AFTER_RULE;
219 }
220
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900221 void ParseInclude(StringPiece line, StringPiece directive) {
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900222 IncludeAST* ast = new IncludeAST();
Shinichiro Hamaji861bd642015-06-19 16:59:13 +0900223 ast->set_loc(loc_);
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900224 ast->expr = ParseExpr(line);
Shinichiro Hamajiefad2dd2015-06-17 03:08:02 +0900225 ast->should_exist = directive[0] == 'i';
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900226 out_asts_->push_back(ast);
227 }
228
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900229 void ParseDefine(StringPiece line, StringPiece) {
230 if (line.empty()) {
231 Error("*** empty variable name.");
232 }
233 define_name_ = line;
234 define_start_ = 0;
235 define_start_line_ = loc_.lineno;
236 }
237
238 void ParseInsideDefine(StringPiece line) {
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900239 line = TrimLeftSpace(line);
240 if (GetDirective(line) != "endef") {
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900241 if (define_start_ == 0)
242 define_start_ = l_;
243 return;
244 }
245
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900246 StringPiece rest = TrimRightSpace(RemoveComment(TrimLeftSpace(
247 line.substr(sizeof("endef")))));
248 if (!rest.empty()) {
249 WARN("%s:%d: extraneous text after `endef' directive", LOCF(loc_));
250 }
251
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900252 AssignAST* ast = new AssignAST();
253 ast->set_loc(Loc(loc_.filename, define_start_line_));
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900254 ast->lhs = ParseExpr(define_name_);
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900255 StringPiece rhs;
256 if (define_start_)
Shinichiro Hamaji32750622015-06-17 14:57:33 +0900257 rhs = TrimRightSpace(buf_.substr(define_start_, l_ - define_start_));
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900258 ast->rhs = ParseExpr(rhs, ParseExprOpt::DEFINE);
Shinichiro Hamaji81699be2015-06-22 18:07:38 +0900259 ast->orig_rhs = rhs;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900260 ast->op = AssignOp::EQ;
261 ast->directive = AssignDirective::NONE;
262 out_asts_->push_back(ast);
263 define_name_.clear();
264 }
265
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900266 void EnterIf(IfAST* ast) {
267 IfState* st = new IfState();
268 st->ast = ast;
269 st->is_in_else = false;
270 st->num_nest = num_if_nest_;
271 if_stack_.push(st);
272 out_asts_ = &ast->true_asts;
273 }
274
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900275 void ParseIfdef(StringPiece line, StringPiece directive) {
276 IfAST* ast = new IfAST();
277 ast->set_loc(loc_);
278 ast->op = directive[2] == 'n' ? CondOp::IFNDEF : CondOp::IFDEF;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900279 ast->lhs = ParseExpr(line);
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900280 ast->rhs = NULL;
281 out_asts_->push_back(ast);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900282 EnterIf(ast);
283 }
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900284
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900285 bool ParseIfEqCond(StringPiece s, IfAST* ast) {
286 if (s.empty()) {
287 return false;
288 }
289
290 if (s[0] == '(' && s[s.size() - 1] == ')') {
291 s = s.substr(1, s.size() - 2);
292 char terms[] = {',', '\0'};
293 size_t n;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900294 ast->lhs = ParseExprImpl(s, terms, ParseExprOpt::NORMAL, &n, true);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900295 if (s[n] != ',')
296 return false;
297 s = TrimLeftSpace(s.substr(n+1));
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900298 ast->rhs = ParseExprImpl(s, NULL, ParseExprOpt::NORMAL, &n);
Shinichiro Hamajiadeea692015-06-17 17:57:31 +0900299 s = TrimLeftSpace(s.substr(n));
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900300 } else {
301 for (int i = 0; i < 2; i++) {
302 if (s.empty())
303 return false;
304 char quote = s[0];
305 if (quote != '\'' && quote != '"')
306 return false;
307 size_t end = s.find(quote, 1);
308 if (end == string::npos)
309 return false;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900310 Value* v = ParseExpr(s.substr(1, end - 1), ParseExprOpt::NORMAL);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900311 if (i == 0)
312 ast->lhs = v;
313 else
314 ast->rhs = v;
315 s = TrimLeftSpace(s.substr(end+1));
316 }
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900317 }
Shinichiro Hamajiadeea692015-06-17 17:57:31 +0900318 if (!s.empty()) {
319 Error("extraneous text after `ifeq' directive");
320 }
321 return true;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900322 }
323
324 void ParseIfeq(StringPiece line, StringPiece directive) {
325 IfAST* ast = new IfAST();
326 ast->set_loc(loc_);
327 ast->op = directive[2] == 'n' ? CondOp::IFNEQ : CondOp::IFEQ;
328
329 if (!ParseIfEqCond(line, ast)) {
330 Error("*** invalid syntax in conditional.");
331 }
332
333 out_asts_->push_back(ast);
334 EnterIf(ast);
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900335 }
336
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900337 void ParseElse(StringPiece line, StringPiece) {
338 CheckIfStack("else");
339 IfState* st = if_stack_.top();
340 if (st->is_in_else)
341 Error("*** only one `else' per conditional.");
342 st->is_in_else = true;
343 out_asts_ = &st->ast->false_asts;
344
345 StringPiece next_if = TrimLeftSpace(line);
346 if (next_if.empty())
347 return;
348
349 num_if_nest_ = st->num_nest + 1;
350 if (!HandleDirective(next_if, else_if_directives_)) {
351 WARN("%s:%d: extraneous text after `else' directive", LOCF(loc_));
352 }
353 num_if_nest_ = 0;
354 }
355
356 void ParseEndif(StringPiece line, StringPiece) {
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900357 CheckIfStack("endif");
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900358 if (!line.empty())
359 Error("extraneous text after `endif` directive");
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900360 IfState st = *if_stack_.top();
361 for (int t = 0; t <= st.num_nest; t++) {
362 delete if_stack_.top();
363 if_stack_.pop();
364 if (if_stack_.empty()) {
365 out_asts_ = asts_;
366 } else {
367 IfState* st = if_stack_.top();
368 if (st->is_in_else)
Shinichiro Hamaji2847f092015-06-17 15:48:37 +0900369 out_asts_ = &st->ast->false_asts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900370 else
Shinichiro Hamaji2847f092015-06-17 15:48:37 +0900371 out_asts_ = &st->ast->true_asts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900372 }
373 }
374 }
375
376 void CheckIfStack(const char* keyword) {
377 if (if_stack_.empty()) {
378 Error(StringPrintf("*** extraneous `%s'.", keyword));
379 }
380 }
381
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900382 StringPiece RemoveComment(StringPiece line) {
Shinichiro Hamajieafd0522015-06-18 16:46:02 +0900383 size_t i = FindOutsideParen(line, '#');
384 if (i == string::npos)
385 return line;
386 return line.substr(0, i);
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900387 }
388
389 StringPiece GetDirective(StringPiece line) {
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900390 if (line.size() < shortest_directive_len_)
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900391 return StringPiece();
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900392 StringPiece prefix = line.substr(0, longest_directive_len_ + 1);
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900393 size_t space_index = prefix.find_first_of(" \t#");
394 return prefix.substr(0, space_index);
395 }
396
397 bool HandleDirective(StringPiece line, const DirectiveMap* directive_map) {
398 StringPiece directive = GetDirective(line);
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900399 auto found = directive_map->find(directive);
400 if (found == directive_map->end())
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900401 return false;
402
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900403 StringPiece rest = TrimRightSpace(RemoveComment(TrimLeftSpace(
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900404 line.substr(directive.size()))));
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900405 (this->*found->second)(rest, directive);
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900406 return true;
407 }
408
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900409 StringPiece buf_;
410 size_t l_;
411 ParserState state_;
412
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900413 vector<AST*>* asts_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900414 vector<AST*>* out_asts_;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900415
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900416 StringPiece define_name_;
417 size_t define_start_;
418 int define_start_line_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900419
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900420 int num_if_nest_;
421 stack<IfState*> if_stack_;
422
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900423 Loc loc_;
424 bool fixed_lineno_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900425
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900426 static DirectiveMap* make_directives_;
427 static DirectiveMap* else_if_directives_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900428 static size_t shortest_directive_len_;
429 static size_t longest_directive_len_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900430};
431
432void Parse(Makefile* mk) {
433 Parser parser(StringPiece(mk->buf(), mk->len()),
434 mk->filename().c_str(),
435 mk->mutable_asts());
436 parser.Parse();
437}
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900438
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900439void Parse(StringPiece buf, const Loc& loc, vector<AST*>* out_asts) {
440 Parser parser(buf, loc, out_asts);
441 parser.Parse();
442}
443
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900444void InitParser() {
445 Parser::Init();
446}
447
448void QuitParser() {
449 Parser::Quit();
450}
451
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900452Parser::DirectiveMap* Parser::make_directives_;
453Parser::DirectiveMap* Parser::else_if_directives_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900454size_t Parser::shortest_directive_len_;
455size_t Parser::longest_directive_len_;
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900456
457void ParseAssignStatement(StringPiece line, size_t sep,
458 StringPiece* lhs, StringPiece* rhs, AssignOp* op) {
459 CHECK(sep != 0);
460 *op = AssignOp::EQ;
461 size_t lhs_end = sep;
462 switch (line[sep-1]) {
463 case ':':
464 lhs_end--;
465 *op = AssignOp::COLON_EQ;
466 break;
467 case '+':
468 lhs_end--;
469 *op = AssignOp::PLUS_EQ;
470 break;
471 case '?':
472 lhs_end--;
473 *op = AssignOp::QUESTION_EQ;
474 break;
475 }
476 *lhs = TrimSpace(line.substr(0, lhs_end));
477 *rhs = TrimSpace(line.substr(sep + 1));
478}