blob: 3bec5be5d70d7ce368ff175a7c0f16bc0637d86d [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 Hamaji776ca302015-06-06 03:52:48 +090022#include "ast.h"
23#include "file.h"
24#include "loc.h"
25#include "log.h"
26#include "string_piece.h"
Shinichiro Hamaji810fd032015-06-17 04:38:03 +090027#include "strutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090028#include "value.h"
29
30enum struct ParserState {
31 NOT_AFTER_RULE = 0,
32 AFTER_RULE,
33 MAYBE_AFTER_RULE,
34};
35
36class Parser {
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090037 struct IfState {
38 IfAST* ast;
39 bool is_in_else;
40 int num_nest;
41 };
42
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +090043 typedef void (Parser::*DirectiveHandler)(
44 StringPiece line, StringPiece directive);
45 typedef unordered_map<StringPiece, DirectiveHandler> DirectiveMap;
46
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090047 public:
48 Parser(StringPiece buf, const char* filename, vector<AST*>* asts)
49 : buf_(buf),
50 state_(ParserState::NOT_AFTER_RULE),
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090051 asts_(asts),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090052 out_asts_(asts),
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090053 num_if_nest_(0),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090054 loc_(filename, 0),
55 fixed_lineno_(false) {
56 }
57
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +090058 Parser(StringPiece buf, const Loc& loc, vector<AST*>* asts)
59 : buf_(buf),
60 state_(ParserState::NOT_AFTER_RULE),
61 asts_(asts),
62 out_asts_(asts),
63 num_if_nest_(0),
64 loc_(loc),
65 fixed_lineno_(true) {
66 }
67
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090068 ~Parser() {
69 }
70
71 void Parse() {
72 l_ = 0;
73
74 for (l_ = 0; l_ < buf_.size();) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090075 size_t lf_cnt = 0;
76 size_t e = FindEndOfLine(&lf_cnt);
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +090077 if (!fixed_lineno_)
78 loc_.lineno += lf_cnt;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090079 StringPiece line(buf_.data() + l_, e - l_);
80 ParseLine(line);
81 if (e == buf_.size())
82 break;
83
84 l_ = e + 1;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090085 }
86 }
87
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +090088 static void Init() {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +090089 make_directives_ = new DirectiveMap;
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +090090 (*make_directives_)["include"] = &Parser::ParseInclude;
91 (*make_directives_)["-include"] = &Parser::ParseInclude;
92 (*make_directives_)["sinclude"] = &Parser::ParseInclude;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +090093 (*make_directives_)["define"] = &Parser::ParseDefine;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090094 (*make_directives_)["ifdef"] = &Parser::ParseIfdef;
95 (*make_directives_)["ifndef"] = &Parser::ParseIfdef;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +090096 (*make_directives_)["ifeq"] = &Parser::ParseIfeq;
97 (*make_directives_)["ifneq"] = &Parser::ParseIfeq;
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +090098 (*make_directives_)["else"] = &Parser::ParseElse;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +090099 (*make_directives_)["endif"] = &Parser::ParseEndif;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900100
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900101 else_if_directives_ = new DirectiveMap;
102 (*else_if_directives_)["ifdef"] = &Parser::ParseIfdef;
103 (*else_if_directives_)["ifndef"] = &Parser::ParseIfdef;
104
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900105 shortest_directive_len_ = 9999;
106 longest_directive_len_ = 0;
107 for (auto p : *make_directives_) {
108 size_t len = p.first.size();
109 shortest_directive_len_ = min(len, shortest_directive_len_);
110 longest_directive_len_ = max(len, longest_directive_len_);
111 }
112 }
113
114 static void Quit() {
115 delete make_directives_;
116 }
117
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900118 private:
119 void Error(const string& msg) {
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +0900120 ERROR("%s:%d: %s", LOCF(loc_), msg.c_str());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900121 }
122
123 size_t FindEndOfLine(size_t* lf_cnt) {
124 size_t e = l_;
125 bool prev_backslash = false;
126 for (; e < buf_.size(); e++) {
127 char c = buf_[e];
128 if (c == '\\') {
129 prev_backslash = !prev_backslash;
130 } else if (c == '\n') {
131 ++*lf_cnt;
132 if (!prev_backslash) {
133 return e;
134 }
135 } else if (c != '\r') {
136 prev_backslash = false;
137 }
138 }
139 return e;
140 }
141
142 void ParseLine(StringPiece line) {
143 if (line.empty() || (line.size() == 1 && line[0] == '\r'))
144 return;
145
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900146 if (!define_name_.empty()) {
147 ParseInsideDefine(line);
148 return;
149 }
150
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900151 if (line[0] == '\t' && state_ != ParserState::NOT_AFTER_RULE) {
152 CommandAST* ast = new CommandAST();
Shinichiro Hamaji861bd642015-06-19 16:59:13 +0900153 ast->set_loc(loc_);
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900154 ast->expr = ParseExpr(line.substr(1), ParseExprOpt::COMMAND);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900155 out_asts_->push_back(ast);
156 return;
157 }
158
Shinichiro Hamaji32750622015-06-17 14:57:33 +0900159 line = TrimLeftSpace(line);
Shinichiro Hamajid4e81932015-06-17 04:40:45 +0900160
161 if (line[0] == '#')
162 return;
163
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900164 if (HandleDirective(line, make_directives_)) {
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900165 return;
166 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900167
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900168 size_t sep = FindTwoOutsideParen(line, ':', '=');
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900169 if (sep == string::npos) {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900170 ParseRule(line, sep);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900171 } else if (line[sep] == '=') {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900172 ParseAssign(line, sep);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900173 } else if (line.get(sep+1) == '=') {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900174 ParseAssign(line, sep+1);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900175 } else if (line[sep] == ':') {
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900176 ParseRule(line, sep);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900177 } else {
178 CHECK(false);
179 }
180 }
181
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900182 void ParseRule(StringPiece line, size_t sep) {
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900183 const bool is_rule = sep != string::npos && line[sep] == ':';
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900184 RuleAST* ast = new RuleAST();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900185 ast->set_loc(loc_);
186
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900187 size_t found = FindTwoOutsideParen(line.substr(sep + 1), '=', ';');
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900188 if (found != string::npos) {
189 found += sep + 1;
190 ast->term = line[found];
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900191 ParseExprOpt opt =
192 ast->term == ';' ? ParseExprOpt::COMMAND : ParseExprOpt::NORMAL;
193 ast->after_term = ParseExpr(TrimLeftSpace(line.substr(found + 1)), opt);
194 ast->expr = ParseExpr(TrimSpace(line.substr(0, found)));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900195 } else {
196 ast->term = 0;
197 ast->after_term = NULL;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900198 ast->expr = ParseExpr(TrimSpace(line));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900199 }
200 out_asts_->push_back(ast);
201 state_ = is_rule ? ParserState::AFTER_RULE : ParserState::MAYBE_AFTER_RULE;
202 }
203
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900204 void ParseAssign(StringPiece line, size_t sep) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900205 if (sep == 0)
206 Error("*** empty variable name ***");
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900207 StringPiece lhs;
208 StringPiece rhs;
209 AssignOp op;
210 ParseAssignStatement(line, sep, &lhs, &rhs, &op);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900211
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900212 AssignAST* ast = new AssignAST();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900213 ast->set_loc(loc_);
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900214 ast->lhs = ParseExpr(lhs);
215 ast->rhs = ParseExpr(rhs);
Shinichiro Hamaji81699be2015-06-22 18:07:38 +0900216 ast->orig_rhs = rhs;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900217 ast->op = op;
218 ast->directive = AssignDirective::NONE;
219 out_asts_->push_back(ast);
220 state_ = ParserState::NOT_AFTER_RULE;
221 }
222
Shinichiro Hamaji14b8bea2015-06-17 03:14:28 +0900223 void ParseInclude(StringPiece line, StringPiece directive) {
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900224 IncludeAST* ast = new IncludeAST();
Shinichiro Hamaji861bd642015-06-19 16:59:13 +0900225 ast->set_loc(loc_);
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900226 ast->expr = ParseExpr(line);
Shinichiro Hamajiefad2dd2015-06-17 03:08:02 +0900227 ast->should_exist = directive[0] == 'i';
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900228 out_asts_->push_back(ast);
229 }
230
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900231 void ParseDefine(StringPiece line, StringPiece) {
232 if (line.empty()) {
233 Error("*** empty variable name.");
234 }
235 define_name_ = line;
236 define_start_ = 0;
237 define_start_line_ = loc_.lineno;
238 }
239
240 void ParseInsideDefine(StringPiece line) {
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900241 line = TrimLeftSpace(line);
242 if (GetDirective(line) != "endef") {
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900243 if (define_start_ == 0)
244 define_start_ = l_;
245 return;
246 }
247
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900248 StringPiece rest = TrimRightSpace(RemoveComment(TrimLeftSpace(
249 line.substr(sizeof("endef")))));
250 if (!rest.empty()) {
251 WARN("%s:%d: extraneous text after `endef' directive", LOCF(loc_));
252 }
253
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900254 AssignAST* ast = new AssignAST();
255 ast->set_loc(Loc(loc_.filename, define_start_line_));
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900256 ast->lhs = ParseExpr(define_name_);
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900257 StringPiece rhs;
258 if (define_start_)
Shinichiro Hamaji32750622015-06-17 14:57:33 +0900259 rhs = TrimRightSpace(buf_.substr(define_start_, l_ - define_start_));
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900260 ast->rhs = ParseExpr(rhs, ParseExprOpt::DEFINE);
Shinichiro Hamaji81699be2015-06-22 18:07:38 +0900261 ast->orig_rhs = rhs;
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900262 ast->op = AssignOp::EQ;
263 ast->directive = AssignDirective::NONE;
264 out_asts_->push_back(ast);
265 define_name_.clear();
266 }
267
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900268 void EnterIf(IfAST* ast) {
269 IfState* st = new IfState();
270 st->ast = ast;
271 st->is_in_else = false;
272 st->num_nest = num_if_nest_;
273 if_stack_.push(st);
274 out_asts_ = &ast->true_asts;
275 }
276
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900277 void ParseIfdef(StringPiece line, StringPiece directive) {
278 IfAST* ast = new IfAST();
279 ast->set_loc(loc_);
280 ast->op = directive[2] == 'n' ? CondOp::IFNDEF : CondOp::IFDEF;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900281 ast->lhs = ParseExpr(line);
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900282 ast->rhs = NULL;
283 out_asts_->push_back(ast);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900284 EnterIf(ast);
285 }
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900286
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900287 bool ParseIfEqCond(StringPiece s, IfAST* ast) {
288 if (s.empty()) {
289 return false;
290 }
291
292 if (s[0] == '(' && s[s.size() - 1] == ')') {
293 s = s.substr(1, s.size() - 2);
294 char terms[] = {',', '\0'};
295 size_t n;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900296 ast->lhs = ParseExprImpl(s, terms, ParseExprOpt::NORMAL, &n, true);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900297 if (s[n] != ',')
298 return false;
299 s = TrimLeftSpace(s.substr(n+1));
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900300 ast->rhs = ParseExprImpl(s, NULL, ParseExprOpt::NORMAL, &n);
Shinichiro Hamajiadeea692015-06-17 17:57:31 +0900301 s = TrimLeftSpace(s.substr(n));
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900302 } else {
303 for (int i = 0; i < 2; i++) {
304 if (s.empty())
305 return false;
306 char quote = s[0];
307 if (quote != '\'' && quote != '"')
308 return false;
309 size_t end = s.find(quote, 1);
310 if (end == string::npos)
311 return false;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900312 Value* v = ParseExpr(s.substr(1, end - 1), ParseExprOpt::NORMAL);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900313 if (i == 0)
314 ast->lhs = v;
315 else
316 ast->rhs = v;
317 s = TrimLeftSpace(s.substr(end+1));
318 }
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900319 }
Shinichiro Hamajiadeea692015-06-17 17:57:31 +0900320 if (!s.empty()) {
321 Error("extraneous text after `ifeq' directive");
322 }
323 return true;
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900324 }
325
326 void ParseIfeq(StringPiece line, StringPiece directive) {
327 IfAST* ast = new IfAST();
328 ast->set_loc(loc_);
329 ast->op = directive[2] == 'n' ? CondOp::IFNEQ : CondOp::IFEQ;
330
331 if (!ParseIfEqCond(line, ast)) {
332 Error("*** invalid syntax in conditional.");
333 }
334
335 out_asts_->push_back(ast);
336 EnterIf(ast);
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900337 }
338
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900339 void ParseElse(StringPiece line, StringPiece) {
340 CheckIfStack("else");
341 IfState* st = if_stack_.top();
342 if (st->is_in_else)
343 Error("*** only one `else' per conditional.");
344 st->is_in_else = true;
345 out_asts_ = &st->ast->false_asts;
346
347 StringPiece next_if = TrimLeftSpace(line);
348 if (next_if.empty())
349 return;
350
351 num_if_nest_ = st->num_nest + 1;
352 if (!HandleDirective(next_if, else_if_directives_)) {
353 WARN("%s:%d: extraneous text after `else' directive", LOCF(loc_));
354 }
355 num_if_nest_ = 0;
356 }
357
358 void ParseEndif(StringPiece line, StringPiece) {
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900359 CheckIfStack("endif");
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900360 if (!line.empty())
361 Error("extraneous text after `endif` directive");
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900362 IfState st = *if_stack_.top();
363 for (int t = 0; t <= st.num_nest; t++) {
364 delete if_stack_.top();
365 if_stack_.pop();
366 if (if_stack_.empty()) {
367 out_asts_ = asts_;
368 } else {
369 IfState* st = if_stack_.top();
370 if (st->is_in_else)
Shinichiro Hamaji2847f092015-06-17 15:48:37 +0900371 out_asts_ = &st->ast->false_asts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900372 else
Shinichiro Hamaji2847f092015-06-17 15:48:37 +0900373 out_asts_ = &st->ast->true_asts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900374 }
375 }
376 }
377
378 void CheckIfStack(const char* keyword) {
379 if (if_stack_.empty()) {
380 Error(StringPrintf("*** extraneous `%s'.", keyword));
381 }
382 }
383
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900384 StringPiece RemoveComment(StringPiece line) {
Shinichiro Hamajieafd0522015-06-18 16:46:02 +0900385 size_t i = FindOutsideParen(line, '#');
386 if (i == string::npos)
387 return line;
388 return line.substr(0, i);
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900389 }
390
391 StringPiece GetDirective(StringPiece line) {
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900392 if (line.size() < shortest_directive_len_)
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900393 return StringPiece();
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900394 StringPiece prefix = line.substr(0, longest_directive_len_ + 1);
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900395 size_t space_index = prefix.find_first_of(" \t#");
396 return prefix.substr(0, space_index);
397 }
398
399 bool HandleDirective(StringPiece line, const DirectiveMap* directive_map) {
400 StringPiece directive = GetDirective(line);
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900401 auto found = directive_map->find(directive);
402 if (found == directive_map->end())
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900403 return false;
404
Shinichiro Hamaji5562caf2015-06-17 17:08:40 +0900405 StringPiece rest = TrimRightSpace(RemoveComment(TrimLeftSpace(
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900406 line.substr(directive.size()))));
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900407 (this->*found->second)(rest, directive);
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900408 return true;
409 }
410
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900411 StringPiece buf_;
412 size_t l_;
413 ParserState state_;
414
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900415 vector<AST*>* asts_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900416 vector<AST*>* out_asts_;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900417
Shinichiro Hamaji810fd032015-06-17 04:38:03 +0900418 StringPiece define_name_;
419 size_t define_start_;
420 int define_start_line_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900421
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900422 int num_if_nest_;
423 stack<IfState*> if_stack_;
424
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900425 Loc loc_;
426 bool fixed_lineno_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900427
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900428 static DirectiveMap* make_directives_;
429 static DirectiveMap* else_if_directives_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900430 static size_t shortest_directive_len_;
431 static size_t longest_directive_len_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900432};
433
434void Parse(Makefile* mk) {
435 Parser parser(StringPiece(mk->buf(), mk->len()),
436 mk->filename().c_str(),
437 mk->mutable_asts());
438 parser.Parse();
439}
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900440
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900441void Parse(StringPiece buf, const Loc& loc, vector<AST*>* out_asts) {
442 Parser parser(buf, loc, out_asts);
443 parser.Parse();
444}
445
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900446void InitParser() {
447 Parser::Init();
448}
449
450void QuitParser() {
451 Parser::Quit();
452}
453
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900454Parser::DirectiveMap* Parser::make_directives_;
455Parser::DirectiveMap* Parser::else_if_directives_;
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900456size_t Parser::shortest_directive_len_;
457size_t Parser::longest_directive_len_;
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900458
459void ParseAssignStatement(StringPiece line, size_t sep,
460 StringPiece* lhs, StringPiece* rhs, AssignOp* op) {
461 CHECK(sep != 0);
462 *op = AssignOp::EQ;
463 size_t lhs_end = sep;
464 switch (line[sep-1]) {
465 case ':':
466 lhs_end--;
467 *op = AssignOp::COLON_EQ;
468 break;
469 case '+':
470 lhs_end--;
471 *op = AssignOp::PLUS_EQ;
472 break;
473 case '?':
474 lhs_end--;
475 *op = AssignOp::QUESTION_EQ;
476 break;
477 }
478 *lhs = TrimSpace(line.substr(0, lhs_end));
479 *rhs = TrimSpace(line.substr(sep + 1));
480}