blob: 54199002427f515868e70f9aa79e8bc7d67a9647 [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 Hamaji645cca72015-09-24 17:04:21 +090017#include "expr.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090018
19#include <vector>
20
21#include "eval.h"
22#include "func.h"
23#include "log.h"
24#include "stringprintf.h"
25#include "strutil.h"
26#include "var.h"
27
Dan Willemsen3ce083f2017-10-11 22:17:48 -070028Evaluable::Evaluable() {}
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090029
Dan Willemsen3ce083f2017-10-11 22:17:48 -070030Evaluable::~Evaluable() {}
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090031
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +090032string Evaluable::Eval(Evaluator* ev) const {
33 string s;
34 Eval(ev, &s);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090035 return s;
36}
37
Dan Willemsen3ce083f2017-10-11 22:17:48 -070038Value::Value() {}
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090039
Dan Willemsen3ce083f2017-10-11 22:17:48 -070040Value::~Value() {}
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090041
42string Value::DebugString() const {
Colin Cross3f186902015-07-29 17:14:53 -070043 if (static_cast<const Value*>(this)) {
Shinichiro Hamaji810fd032015-06-17 04:38:03 +090044 return NoLineBreak(DebugString_());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090045 }
46 return "(null)";
47}
48
49class Literal : public Value {
50 public:
Dan Willemsen3ce083f2017-10-11 22:17:48 -070051 explicit Literal(StringPiece s) : s_(s) {}
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090052
53 StringPiece val() const { return s_; }
54
Dan Willemsen36e57292017-10-09 11:23:32 -070055 virtual void Eval(Evaluator* ev, string* s) const override {
56 ev->CheckStack();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090057 s->append(s_.begin(), s_.end());
58 }
59
Shinichiro Hamaji4b351ab2016-02-12 19:42:30 +090060 virtual bool IsLiteral() const override { return true; }
Shinichiro Hamaji71f58132016-02-22 16:20:27 +090061 virtual StringPiece GetLiteralValueUnsafe() const override { return s_; }
Shinichiro Hamaji347e06f2016-01-05 14:41:53 +090062
Dan Willemsen3ce083f2017-10-11 22:17:48 -070063 virtual string DebugString_() const override { return s_.as_string(); }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090064
65 private:
66 StringPiece s_;
67};
68
69class Expr : public Value {
70 public:
Dan Willemsen3ce083f2017-10-11 22:17:48 -070071 Expr() {}
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090072
73 virtual ~Expr() {
74 for (Value* v : vals_) {
75 delete v;
76 }
77 }
78
79 // Takes the ownership of |v|.
Dan Willemsen3ce083f2017-10-11 22:17:48 -070080 void AddValue(Value* v) { vals_.push_back(v); }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090081
82 virtual void Eval(Evaluator* ev, string* s) const override {
Dan Willemsen36e57292017-10-09 11:23:32 -070083 ev->CheckStack();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090084 for (Value* v : vals_) {
85 v->Eval(ev, s);
86 }
87 }
88
89 virtual string DebugString_() const override {
90 string r;
91 for (Value* v : vals_) {
92 if (r.empty()) {
93 r += "Expr(";
94 } else {
95 r += ", ";
96 }
97 r += v->DebugString();
98 }
Shinichiro Hamajibaf2c382015-07-07 14:53:02 +090099 if (!r.empty())
100 r += ")";
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900101 return r;
102 }
103
Shinichiro Hamaji4b351ab2016-02-12 19:42:30 +0900104 virtual Value* Compact() override {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900105 if (vals_.size() != 1) {
106 return this;
107 }
108 Value* r = vals_[0];
109 vals_.clear();
110 delete this;
111 return r;
112 }
113
114 private:
115 vector<Value*> vals_;
116};
117
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900118class SymRef : public Value {
119 public:
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700120 explicit SymRef(Symbol n) : name_(n) {}
121 virtual ~SymRef() {}
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900122
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900123 virtual void Eval(Evaluator* ev, string* s) const override {
Dan Willemsen36e57292017-10-09 11:23:32 -0700124 ev->CheckStack();
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900125 Var* v = ev->LookupVar(name_);
Dan Willemsen276e96a2017-10-03 14:24:48 -0700126 v->Used(ev, name_);
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900127 v->Eval(ev, s);
128 }
129
130 virtual string DebugString_() const override {
131 return StringPrintf("SymRef(%s)", name_.c_str());
132 }
133
134 private:
135 Symbol name_;
136};
137
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900138class VarRef : public Value {
139 public:
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700140 explicit VarRef(Value* n) : name_(n) {}
141 virtual ~VarRef() { delete name_; }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900142
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900143 virtual void Eval(Evaluator* ev, string* s) const override {
Dan Willemsen36e57292017-10-09 11:23:32 -0700144 ev->CheckStack();
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900145 ev->IncrementEvalDepth();
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900146 const string&& name = name_->Eval(ev);
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900147 ev->DecrementEvalDepth();
Dan Willemsen276e96a2017-10-03 14:24:48 -0700148 Symbol sym = Intern(name);
149 Var* v = ev->LookupVar(sym);
150 v->Used(ev, sym);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900151 v->Eval(ev, s);
152 }
153
154 virtual string DebugString_() const override {
155 return StringPrintf("VarRef(%s)", name_->DebugString().c_str());
156 }
157
158 private:
159 Value* name_;
160};
161
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900162class VarSubst : public Value {
163 public:
164 explicit VarSubst(Value* n, Value* p, Value* s)
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700165 : name_(n), pat_(p), subst_(s) {}
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900166 virtual ~VarSubst() {
167 delete name_;
168 delete pat_;
169 delete subst_;
170 }
171
172 virtual void Eval(Evaluator* ev, string* s) const override {
Dan Willemsen36e57292017-10-09 11:23:32 -0700173 ev->CheckStack();
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900174 ev->IncrementEvalDepth();
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900175 const string&& name = name_->Eval(ev);
Dan Willemsen276e96a2017-10-03 14:24:48 -0700176 Symbol sym = Intern(name);
177 Var* v = ev->LookupVar(sym);
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900178 const string&& pat_str = pat_->Eval(ev);
179 const string&& subst = subst_->Eval(ev);
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900180 ev->DecrementEvalDepth();
Dan Willemsen276e96a2017-10-03 14:24:48 -0700181 v->Used(ev, sym);
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900182 const string&& value = v->Eval(ev);
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +0900183 WordWriter ww(s);
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900184 Pattern pat(pat_str);
185 for (StringPiece tok : WordScanner(value)) {
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +0900186 ww.MaybeAddWhitespace();
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900187 pat.AppendSubstRef(tok, subst, s);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900188 }
189 }
190
191 virtual string DebugString_() const override {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700192 return StringPrintf("VarSubst(%s:%s=%s)", name_->DebugString().c_str(),
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900193 pat_->DebugString().c_str(),
194 subst_->DebugString().c_str());
195 }
196
197 private:
198 Value* name_;
199 Value* pat_;
200 Value* subst_;
201};
202
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900203class Func : public Value {
204 public:
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700205 explicit Func(FuncInfo* fi) : fi_(fi) {}
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900206
Shinichiro Hamajid0e188e2015-06-16 18:53:01 +0900207 ~Func() {
208 for (Value* a : args_)
209 delete a;
210 }
211
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900212 virtual void Eval(Evaluator* ev, string* s) const override {
Dan Willemsen36e57292017-10-09 11:23:32 -0700213 ev->CheckStack();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900214 LOG("Invoke func %s(%s)", name(), JoinValues(args_, ",").c_str());
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900215 ev->IncrementEvalDepth();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900216 fi_->func(args_, ev, s);
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900217 ev->DecrementEvalDepth();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900218 }
219
220 virtual string DebugString_() const override {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700221 return StringPrintf("Func(%s %s)", fi_->name,
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900222 JoinValues(args_, ",").c_str());
223 }
224
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700225 void AddArg(Value* v) { args_.push_back(v); }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900226
227 const char* name() const { return fi_->name; }
228 int arity() const { return fi_->arity; }
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900229 int min_arity() const { return fi_->min_arity; }
230 bool trim_space() const { return fi_->trim_space; }
231 bool trim_right_space_1st() const { return fi_->trim_right_space_1st; }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900232
233 private:
234 FuncInfo* fi_;
235 vector<Value*> args_;
236};
237
238static char CloseParen(char c) {
239 switch (c) {
240 case '(':
241 return ')';
242 case '{':
243 return '}';
244 }
245 return 0;
246}
247
248static size_t SkipSpaces(StringPiece s, const char* terms) {
249 for (size_t i = 0; i < s.size(); i++) {
250 char c = s[i];
Shinichiro Hamaji64cf8912015-06-26 09:25:19 +0900251 if (strchr(terms, c))
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900252 return i;
Shinichiro Hamaji64cf8912015-06-26 09:25:19 +0900253 if (!isspace(c)) {
254 if (c != '\\')
255 return i;
256 char n = s.get(i + 1);
257 if (n != '\r' && n != '\n')
258 return i;
259 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900260 }
261 return s.size();
262}
263
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900264bool ShouldHandleComments(ParseExprOpt opt) {
265 return opt != ParseExprOpt::DEFINE && opt != ParseExprOpt::COMMAND;
266}
267
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900268void ParseFunc(const Loc& loc,
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700269 Func* f,
270 StringPiece s,
271 size_t i,
272 char* terms,
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900273 size_t* index_out) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900274 terms[1] = ',';
275 terms[2] = '\0';
276 i += SkipSpaces(s.substr(i), terms);
277 if (i == s.size()) {
278 *index_out = i;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900279 return;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900280 }
281
282 int nargs = 1;
283 while (true) {
284 if (f->arity() && nargs >= f->arity()) {
285 terms[1] = '\0'; // Drop ','.
286 }
287
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900288 if (f->trim_space()) {
Shinichiro Hamajic8b4b1c2015-07-07 14:57:53 +0900289 for (; i < s.size(); i++) {
290 if (isspace(s[i]))
291 continue;
292 if (s[i] == '\\') {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700293 char c = s.get(i + 1);
Shinichiro Hamajic8b4b1c2015-07-07 14:57:53 +0900294 if (c == '\r' || c == '\n')
295 continue;
296 }
297 break;
298 }
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900299 }
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700300 const bool trim_right_space =
301 (f->trim_space() || (nargs == 1 && f->trim_right_space_1st()));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900302 size_t n;
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700303 Value* v = ParseExprImpl(loc, s.substr(i), terms, ParseExprOpt::FUNC, &n,
304 trim_right_space);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900305 // TODO: concatLine???
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900306 f->AddArg(v);
307 i += n;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900308 if (i == s.size()) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700309 ERROR_LOC(loc,
310 "*** unterminated call to function '%s': "
Dan Willemsene41c7552017-02-22 14:31:16 -0800311 "missing '%c'.",
312 f->name(), terms[0]);
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900313 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900314 nargs++;
315 if (s[i] == terms[0]) {
316 i++;
317 break;
318 }
319 i++; // Should be ','.
320 if (i == s.size())
321 break;
322 }
323
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900324 if (nargs <= f->min_arity()) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700325 ERROR_LOC(loc,
326 "*** insufficient number of arguments (%d) to function `%s'.",
Dan Willemsene41c7552017-02-22 14:31:16 -0800327 nargs - 1, f->name());
Shinichiro Hamaji81b2d0f2015-06-16 19:25:35 +0900328 }
329
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900330 *index_out = i;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900331 return;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900332}
333
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900334Value* ParseDollar(const Loc& loc, StringPiece s, size_t* index_out) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900335 CHECK(s.size() >= 2);
336 CHECK(s[0] == '$');
337 CHECK(s[1] != '$');
338
339 char cp = CloseParen(s[1]);
340 if (cp == 0) {
341 *index_out = 2;
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900342 return new SymRef(Intern(s.substr(1, 1)));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900343 }
344
345 char terms[] = {cp, ':', ' ', 0};
346 for (size_t i = 2;;) {
347 size_t n;
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700348 Value* vname =
349 ParseExprImpl(loc, s.substr(i), terms, ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900350 i += n;
351 if (s[i] == cp) {
352 *index_out = i + 1;
Shinichiro Hamaji347e06f2016-01-05 14:41:53 +0900353 if (vname->IsLiteral()) {
354 Literal* lit = static_cast<Literal*>(vname);
Shinichiro Hamaji82e20092015-11-17 15:18:28 +0900355 Symbol sym = Intern(lit->val());
356 if (g_flags.enable_kati_warnings) {
357 size_t found = sym.str().find_first_of(" ({");
358 if (found != string::npos) {
Dan Willemsene41c7552017-02-22 14:31:16 -0800359 KATI_WARN_LOC(loc, "*warning*: variable lookup with '%c': %.*s",
360 sym.str()[found], SPF(s));
Shinichiro Hamaji82e20092015-11-17 15:18:28 +0900361 }
362 }
363 Value* r = new SymRef(sym);
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900364 delete lit;
365 return r;
366 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900367 return new VarRef(vname);
368 }
369
Shinichiro Hamajia0315fc2015-06-26 08:15:55 +0900370 if (s[i] == ' ' || s[i] == '\\') {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900371 // ${func ...}
Shinichiro Hamaji347e06f2016-01-05 14:41:53 +0900372 if (vname->IsLiteral()) {
373 Literal* lit = static_cast<Literal*>(vname);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900374 if (FuncInfo* fi = GetFuncInfo(lit->val())) {
Shinichiro Hamajid0e188e2015-06-16 18:53:01 +0900375 delete lit;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900376 Func* func = new Func(fi);
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700377 ParseFunc(loc, func, s, i + 1, terms, index_out);
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900378 return func;
Shinichiro Hamaji82e20092015-11-17 15:18:28 +0900379 } else {
Dan Willemsene41c7552017-02-22 14:31:16 -0800380 KATI_WARN_LOC(loc, "*warning*: unknown make function '%.*s': %.*s",
381 SPF(lit->val()), SPF(s));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900382 }
383 }
384
385 // Not a function. Drop ' ' from |terms| and parse it
386 // again. This is inefficient, but this code path should be
387 // rarely used.
388 delete vname;
389 terms[2] = 0;
390 i = 2;
391 continue;
392 }
393
394 if (s[i] == ':') {
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900395 terms[2] = '\0';
396 terms[1] = '=';
397 size_t n;
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700398 Value* pat =
399 ParseExprImpl(loc, s.substr(i + 1), terms, ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900400 i += 1 + n;
401 if (s[i] == cp) {
402 Expr* v = new Expr;
403 v->AddValue(vname);
404 v->AddValue(new Literal(":"));
405 v->AddValue(pat);
Shinichiro Hamajif72e0242015-06-26 00:38:27 +0900406 *index_out = i + 1;
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900407 return new VarRef(v);
408 }
409
410 terms[1] = '\0';
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700411 Value* subst =
412 ParseExprImpl(loc, s.substr(i + 1), terms, ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900413 i += 1 + n;
Shinichiro Hamajif72e0242015-06-26 00:38:27 +0900414 *index_out = i + 1;
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900415 return new VarSubst(vname->Compact(), pat, subst);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900416 }
417
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900418 // GNU make accepts expressions like $((). See unmatched_paren*.mk
419 // for detail.
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900420 size_t found = s.find(cp);
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900421 if (found != string::npos) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700422 KATI_WARN_LOC(loc, "*warning*: unmatched parentheses: %.*s", SPF(s));
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900423 *index_out = s.size();
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700424 return new SymRef(Intern(s.substr(2, found - 2)));
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900425 }
Dan Willemsene41c7552017-02-22 14:31:16 -0800426 ERROR_LOC(loc, "*** unterminated variable reference.");
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900427 }
428}
429
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900430Value* ParseExprImpl(const Loc& loc,
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700431 StringPiece s,
432 const char* terms,
433 ParseExprOpt opt,
434 size_t* index_out,
435 bool trim_right_space) {
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900436 if (s.get(s.size() - 1) == '\r')
437 s.remove_suffix(1);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900438
439 Expr* r = new Expr;
440 size_t b = 0;
441 char save_paren = 0;
442 int paren_depth = 0;
443 size_t i;
444 for (i = 0; i < s.size(); i++) {
445 char c = s[i];
Shinichiro Hamaji170e8b32015-09-15 15:36:57 +0900446 if (terms && strchr(terms, c) && !save_paren) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900447 break;
448 }
449
450 // Handle a comment.
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900451 if (!terms && c == '#' && ShouldHandleComments(opt)) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900452 if (i > b)
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700453 r->AddValue(new Literal(s.substr(b, i - b)));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900454 bool was_backslash = false;
455 for (; i < s.size() && !(s[i] == '\n' && !was_backslash); i++) {
456 was_backslash = !was_backslash && s[i] == '\\';
457 }
458 *index_out = i;
459 return r->Compact();
460 }
461
462 if (c == '$') {
463 if (i + 1 >= s.size()) {
464 break;
465 }
466
467 if (i > b)
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700468 r->AddValue(new Literal(s.substr(b, i - b)));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900469
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700470 if (s[i + 1] == '$') {
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900471 r->AddValue(new Literal(StringPiece("$")));
Shinichiro Hamajib8a2bb12015-06-26 09:04:57 +0900472 i += 1;
473 b = i + 1;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900474 continue;
475 }
476
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700477 if (terms && strchr(terms, s[i + 1])) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900478 *index_out = i + 1;
479 return r->Compact();
480 }
481
482 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900483 Value* v = ParseDollar(loc, s.substr(i), &n);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900484 i += n;
485 b = i;
486 i--;
487 r->AddValue(v);
488 continue;
489 }
490
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900491 if ((c == '(' || c == '{') && opt == ParseExprOpt::FUNC) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900492 char cp = CloseParen(c);
493 if (terms && terms[0] == cp) {
494 paren_depth++;
495 save_paren = cp;
496 terms++;
497 } else if (cp == save_paren) {
498 paren_depth++;
499 }
500 continue;
501 }
502
503 if (c == save_paren) {
504 paren_depth--;
505 if (paren_depth == 0) {
506 terms--;
507 save_paren = 0;
508 }
509 }
510
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900511 if (c == '\\' && i + 1 < s.size() && opt != ParseExprOpt::COMMAND) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700512 char n = s[i + 1];
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900513 if (n == '\\') {
514 i++;
515 continue;
516 }
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900517 if (n == '#' && ShouldHandleComments(opt)) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700518 r->AddValue(new Literal(s.substr(b, i - b)));
Shinichiro Hamaji7fb82b02015-06-26 00:06:51 +0900519 i++;
520 b = i;
521 continue;
522 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900523 if (n == '\r' || n == '\n') {
Shinichiro Hamajia0315fc2015-06-26 08:15:55 +0900524 if (terms && strchr(terms, ' ')) {
525 break;
526 }
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900527 if (i > b) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700528 r->AddValue(new Literal(TrimRightSpace(s.substr(b, i - b))));
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900529 }
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900530 r->AddValue(new Literal(StringPiece(" ")));
Dan Willemsenae8fc802015-08-20 13:46:14 -0700531 // Skip the current escaped newline
532 i += 2;
Shinichiro Hamaji3e98b6b2016-06-07 14:35:41 +0900533 if (n == '\r' && s.get(i) == '\n')
534 i++;
Dan Willemsenae8fc802015-08-20 13:46:14 -0700535 // Then continue skipping escaped newlines, spaces, and tabs
536 for (; i < s.size(); i++) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700537 if (s[i] == '\\' && (s.get(i + 1) == '\r' || s.get(i + 1) == '\n')) {
Dan Willemsenae8fc802015-08-20 13:46:14 -0700538 i++;
539 continue;
540 }
541 if (s[i] != ' ' && s[i] != '\t') {
Shinichiro Hamaji8f464582015-06-24 20:41:46 +0900542 break;
543 }
544 }
545 b = i;
546 i--;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900547 }
548 }
549 }
550
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900551 if (i > b) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700552 StringPiece rest = s.substr(b, i - b);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900553 if (trim_right_space)
554 rest = TrimRightSpace(rest);
555 if (!rest.empty())
556 r->AddValue(new Literal(rest));
557 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900558 *index_out = i;
559 return r->Compact();
560}
561
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900562Value* ParseExpr(const Loc& loc, StringPiece s, ParseExprOpt opt) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900563 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900564 return ParseExprImpl(loc, s, NULL, opt, &n);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900565}
566
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900567string JoinValues(const vector<Value*>& vals, const char* sep) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900568 vector<string> val_strs;
569 for (Value* v : vals) {
570 val_strs.push_back(v->DebugString());
571 }
572 return JoinStrings(val_strs, sep);
573}
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900574
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900575Value* NewExpr2(Value* v1, Value* v2) {
576 Expr* e = new Expr();
577 e->AddValue(v1);
578 e->AddValue(v2);
579 return e;
580}
581
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900582Value* NewExpr3(Value* v1, Value* v2, Value* v3) {
583 Expr* e = new Expr();
584 e->AddValue(v1);
585 e->AddValue(v2);
586 e->AddValue(v3);
587 return e;
588}
589
Shinichiro Hamajib74b8902015-06-22 18:22:30 +0900590Value* NewLiteral(StringPiece s) {
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900591 return new Literal(s);
592}