blob: 5e7afe6611590dfc4d67d27ce49355be30fdd9c5 [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
28Evaluable::Evaluable() {
29}
30
31Evaluable::~Evaluable() {
32}
33
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +090034string Evaluable::Eval(Evaluator* ev) const {
35 string s;
36 Eval(ev, &s);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090037 return s;
38}
39
40Value::Value() {
41}
42
43Value::~Value() {
44}
45
46string Value::DebugString() const {
Colin Cross3f186902015-07-29 17:14:53 -070047 if (static_cast<const Value*>(this)) {
Shinichiro Hamaji810fd032015-06-17 04:38:03 +090048 return NoLineBreak(DebugString_());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090049 }
50 return "(null)";
51}
52
53class Literal : public Value {
54 public:
55 explicit Literal(StringPiece s)
56 : s_(s) {
57 }
58
59 StringPiece val() const { return s_; }
60
61 virtual void Eval(Evaluator*, string* s) const override {
62 s->append(s_.begin(), s_.end());
63 }
64
Shinichiro Hamaji4b351ab2016-02-12 19:42:30 +090065 virtual bool IsLiteral() const override { return true; }
Shinichiro Hamaji71f58132016-02-22 16:20:27 +090066 virtual StringPiece GetLiteralValueUnsafe() const override { return s_; }
Shinichiro Hamaji347e06f2016-01-05 14:41:53 +090067
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090068 virtual string DebugString_() const override {
69 return s_.as_string();
70 }
71
72 private:
73 StringPiece s_;
74};
75
76class Expr : public Value {
77 public:
78 Expr() {
79 }
80
81 virtual ~Expr() {
82 for (Value* v : vals_) {
83 delete v;
84 }
85 }
86
87 // Takes the ownership of |v|.
88 void AddValue(Value* v) {
89 vals_.push_back(v);
90 }
91
92 virtual void Eval(Evaluator* ev, string* s) const override {
93 for (Value* v : vals_) {
94 v->Eval(ev, s);
95 }
96 }
97
98 virtual string DebugString_() const override {
99 string r;
100 for (Value* v : vals_) {
101 if (r.empty()) {
102 r += "Expr(";
103 } else {
104 r += ", ";
105 }
106 r += v->DebugString();
107 }
Shinichiro Hamajibaf2c382015-07-07 14:53:02 +0900108 if (!r.empty())
109 r += ")";
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900110 return r;
111 }
112
Shinichiro Hamaji4b351ab2016-02-12 19:42:30 +0900113 virtual Value* Compact() override {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900114 if (vals_.size() != 1) {
115 return this;
116 }
117 Value* r = vals_[0];
118 vals_.clear();
119 delete this;
120 return r;
121 }
122
123 private:
124 vector<Value*> vals_;
125};
126
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900127class SymRef : public Value {
128 public:
129 explicit SymRef(Symbol n)
130 : name_(n) {
131 }
132 virtual ~SymRef() {
133 }
134
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900135 virtual void Eval(Evaluator* ev, string* s) const override {
136 Var* v = ev->LookupVar(name_);
137 v->Eval(ev, s);
138 }
139
140 virtual string DebugString_() const override {
141 return StringPrintf("SymRef(%s)", name_.c_str());
142 }
143
144 private:
145 Symbol name_;
146};
147
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900148class VarRef : public Value {
149 public:
150 explicit VarRef(Value* n)
151 : name_(n) {
152 }
153 virtual ~VarRef() {
154 delete name_;
155 }
156
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900157 virtual void Eval(Evaluator* ev, string* s) const override {
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900158 ev->IncrementEvalDepth();
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900159 const string&& name = name_->Eval(ev);
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900160 ev->DecrementEvalDepth();
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900161 Var* v = ev->LookupVar(Intern(name));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900162 v->Eval(ev, s);
163 }
164
165 virtual string DebugString_() const override {
166 return StringPrintf("VarRef(%s)", name_->DebugString().c_str());
167 }
168
169 private:
170 Value* name_;
171};
172
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900173class VarSubst : public Value {
174 public:
175 explicit VarSubst(Value* n, Value* p, Value* s)
176 : name_(n), pat_(p), subst_(s) {
177 }
178 virtual ~VarSubst() {
179 delete name_;
180 delete pat_;
181 delete subst_;
182 }
183
184 virtual void Eval(Evaluator* ev, string* s) const override {
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900185 ev->IncrementEvalDepth();
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900186 const string&& name = name_->Eval(ev);
187 Var* v = ev->LookupVar(Intern(name));
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900188 const string&& pat_str = pat_->Eval(ev);
189 const string&& subst = subst_->Eval(ev);
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900190 ev->DecrementEvalDepth();
191 const string&& value = v->Eval(ev);
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +0900192 WordWriter ww(s);
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900193 Pattern pat(pat_str);
194 for (StringPiece tok : WordScanner(value)) {
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +0900195 ww.MaybeAddWhitespace();
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900196 pat.AppendSubstRef(tok, subst, s);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900197 }
198 }
199
200 virtual string DebugString_() const override {
201 return StringPrintf("VarSubst(%s:%s=%s)",
202 name_->DebugString().c_str(),
203 pat_->DebugString().c_str(),
204 subst_->DebugString().c_str());
205 }
206
207 private:
208 Value* name_;
209 Value* pat_;
210 Value* subst_;
211};
212
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900213class Func : public Value {
214 public:
215 explicit Func(FuncInfo* fi)
216 : fi_(fi) {
217 }
218
Shinichiro Hamajid0e188e2015-06-16 18:53:01 +0900219 ~Func() {
220 for (Value* a : args_)
221 delete a;
222 }
223
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900224 virtual void Eval(Evaluator* ev, string* s) const override {
225 LOG("Invoke func %s(%s)", name(), JoinValues(args_, ",").c_str());
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900226 ev->IncrementEvalDepth();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900227 fi_->func(args_, ev, s);
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900228 ev->DecrementEvalDepth();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900229 }
230
231 virtual string DebugString_() const override {
232 return StringPrintf("Func(%s %s)",
233 fi_->name,
234 JoinValues(args_, ",").c_str());
235 }
236
237 void AddArg(Value* v) {
238 args_.push_back(v);
239 }
240
241 const char* name() const { return fi_->name; }
242 int arity() const { return fi_->arity; }
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900243 int min_arity() const { return fi_->min_arity; }
244 bool trim_space() const { return fi_->trim_space; }
245 bool trim_right_space_1st() const { return fi_->trim_right_space_1st; }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900246
247 private:
248 FuncInfo* fi_;
249 vector<Value*> args_;
250};
251
252static char CloseParen(char c) {
253 switch (c) {
254 case '(':
255 return ')';
256 case '{':
257 return '}';
258 }
259 return 0;
260}
261
262static size_t SkipSpaces(StringPiece s, const char* terms) {
263 for (size_t i = 0; i < s.size(); i++) {
264 char c = s[i];
Shinichiro Hamaji64cf8912015-06-26 09:25:19 +0900265 if (strchr(terms, c))
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900266 return i;
Shinichiro Hamaji64cf8912015-06-26 09:25:19 +0900267 if (!isspace(c)) {
268 if (c != '\\')
269 return i;
270 char n = s.get(i + 1);
271 if (n != '\r' && n != '\n')
272 return i;
273 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900274 }
275 return s.size();
276}
277
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900278bool ShouldHandleComments(ParseExprOpt opt) {
279 return opt != ParseExprOpt::DEFINE && opt != ParseExprOpt::COMMAND;
280}
281
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900282void ParseFunc(const Loc& loc,
283 Func* f, StringPiece s, size_t i, char* terms,
284 size_t* index_out) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900285 terms[1] = ',';
286 terms[2] = '\0';
287 i += SkipSpaces(s.substr(i), terms);
288 if (i == s.size()) {
289 *index_out = i;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900290 return;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900291 }
292
293 int nargs = 1;
294 while (true) {
295 if (f->arity() && nargs >= f->arity()) {
296 terms[1] = '\0'; // Drop ','.
297 }
298
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900299 if (f->trim_space()) {
Shinichiro Hamajic8b4b1c2015-07-07 14:57:53 +0900300 for (; i < s.size(); i++) {
301 if (isspace(s[i]))
302 continue;
303 if (s[i] == '\\') {
304 char c = s.get(i+1);
305 if (c == '\r' || c == '\n')
306 continue;
307 }
308 break;
309 }
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900310 }
311 const bool trim_right_space = (f->trim_space() ||
312 (nargs == 1 && f->trim_right_space_1st()));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900313 size_t n;
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900314 Value* v = ParseExprImpl(loc, s.substr(i), terms, ParseExprOpt::FUNC,
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900315 &n, trim_right_space);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900316 // TODO: concatLine???
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900317 f->AddArg(v);
318 i += n;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900319 if (i == s.size()) {
320 ERROR("%s:%d: *** unterminated call to function '%s': "
321 "missing '%c'.",
322 LOCF(loc), f->name(), terms[0]);
323 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900324 nargs++;
325 if (s[i] == terms[0]) {
326 i++;
327 break;
328 }
329 i++; // Should be ','.
330 if (i == s.size())
331 break;
332 }
333
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900334 if (nargs <= f->min_arity()) {
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900335 ERROR("%s:%d: *** insufficient number of arguments (%d) to function `%s'.",
336 LOCF(loc), nargs - 1, f->name());
Shinichiro Hamaji81b2d0f2015-06-16 19:25:35 +0900337 }
338
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900339 *index_out = i;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900340 return;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900341}
342
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900343Value* ParseDollar(const Loc& loc, StringPiece s, size_t* index_out) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900344 CHECK(s.size() >= 2);
345 CHECK(s[0] == '$');
346 CHECK(s[1] != '$');
347
348 char cp = CloseParen(s[1]);
349 if (cp == 0) {
350 *index_out = 2;
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900351 return new SymRef(Intern(s.substr(1, 1)));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900352 }
353
354 char terms[] = {cp, ':', ' ', 0};
355 for (size_t i = 2;;) {
356 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900357 Value* vname = ParseExprImpl(loc, s.substr(i), terms,
358 ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900359 i += n;
360 if (s[i] == cp) {
361 *index_out = i + 1;
Shinichiro Hamaji347e06f2016-01-05 14:41:53 +0900362 if (vname->IsLiteral()) {
363 Literal* lit = static_cast<Literal*>(vname);
Shinichiro Hamaji82e20092015-11-17 15:18:28 +0900364 Symbol sym = Intern(lit->val());
365 if (g_flags.enable_kati_warnings) {
366 size_t found = sym.str().find_first_of(" ({");
367 if (found != string::npos) {
368 KATI_WARN("%s:%d: *warning*: variable lookup with '%c': %.*s",
369 loc, sym.str()[found], SPF(s));
370 }
371 }
372 Value* r = new SymRef(sym);
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900373 delete lit;
374 return r;
375 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900376 return new VarRef(vname);
377 }
378
Shinichiro Hamajia0315fc2015-06-26 08:15:55 +0900379 if (s[i] == ' ' || s[i] == '\\') {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900380 // ${func ...}
Shinichiro Hamaji347e06f2016-01-05 14:41:53 +0900381 if (vname->IsLiteral()) {
382 Literal* lit = static_cast<Literal*>(vname);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900383 if (FuncInfo* fi = GetFuncInfo(lit->val())) {
Shinichiro Hamajid0e188e2015-06-16 18:53:01 +0900384 delete lit;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900385 Func* func = new Func(fi);
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900386 ParseFunc(loc, func, s, i+1, terms, index_out);
387 return func;
Shinichiro Hamaji82e20092015-11-17 15:18:28 +0900388 } else {
389 KATI_WARN("%s:%d: *warning*: unknown make function '%.*s': %.*s",
390 loc, SPF(lit->val()), SPF(s));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900391 }
392 }
393
394 // Not a function. Drop ' ' from |terms| and parse it
395 // again. This is inefficient, but this code path should be
396 // rarely used.
397 delete vname;
398 terms[2] = 0;
399 i = 2;
400 continue;
401 }
402
403 if (s[i] == ':') {
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900404 terms[2] = '\0';
405 terms[1] = '=';
406 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900407 Value* pat = ParseExprImpl(loc, s.substr(i+1), terms,
408 ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900409 i += 1 + n;
410 if (s[i] == cp) {
411 Expr* v = new Expr;
412 v->AddValue(vname);
413 v->AddValue(new Literal(":"));
414 v->AddValue(pat);
Shinichiro Hamajif72e0242015-06-26 00:38:27 +0900415 *index_out = i + 1;
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900416 return new VarRef(v);
417 }
418
419 terms[1] = '\0';
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900420 Value* subst = ParseExprImpl(loc, s.substr(i+1), terms,
421 ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900422 i += 1 + n;
Shinichiro Hamajif72e0242015-06-26 00:38:27 +0900423 *index_out = i + 1;
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900424 return new VarSubst(vname->Compact(), pat, subst);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900425 }
426
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900427 // GNU make accepts expressions like $((). See unmatched_paren*.mk
428 // for detail.
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900429 size_t found = s.find(cp);
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900430 if (found != string::npos) {
Shinichiro Hamaji82e20092015-11-17 15:18:28 +0900431 KATI_WARN("%s:%d: *warning*: unmatched parentheses: %.*s",
432 loc, SPF(s));
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900433 *index_out = s.size();
434 return new SymRef(Intern(s.substr(2, found-2)));
435 }
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900436 ERROR("%s:%d: *** unterminated variable reference.", LOCF(loc));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900437 }
438}
439
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900440Value* ParseExprImpl(const Loc& loc,
441 StringPiece s, const char* terms, ParseExprOpt opt,
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900442 size_t* index_out, bool trim_right_space) {
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900443 if (s.get(s.size() - 1) == '\r')
444 s.remove_suffix(1);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900445
446 Expr* r = new Expr;
447 size_t b = 0;
448 char save_paren = 0;
449 int paren_depth = 0;
450 size_t i;
451 for (i = 0; i < s.size(); i++) {
452 char c = s[i];
Shinichiro Hamaji170e8b32015-09-15 15:36:57 +0900453 if (terms && strchr(terms, c) && !save_paren) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900454 break;
455 }
456
457 // Handle a comment.
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900458 if (!terms && c == '#' && ShouldHandleComments(opt)) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900459 if (i > b)
460 r->AddValue(new Literal(s.substr(b, i-b)));
461 bool was_backslash = false;
462 for (; i < s.size() && !(s[i] == '\n' && !was_backslash); i++) {
463 was_backslash = !was_backslash && s[i] == '\\';
464 }
465 *index_out = i;
466 return r->Compact();
467 }
468
469 if (c == '$') {
470 if (i + 1 >= s.size()) {
471 break;
472 }
473
474 if (i > b)
475 r->AddValue(new Literal(s.substr(b, i-b)));
476
477 if (s[i+1] == '$') {
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900478 r->AddValue(new Literal(StringPiece("$")));
Shinichiro Hamajib8a2bb12015-06-26 09:04:57 +0900479 i += 1;
480 b = i + 1;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900481 continue;
482 }
483
484 if (terms && strchr(terms, s[i+1])) {
485 *index_out = i + 1;
486 return r->Compact();
487 }
488
489 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900490 Value* v = ParseDollar(loc, s.substr(i), &n);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900491 i += n;
492 b = i;
493 i--;
494 r->AddValue(v);
495 continue;
496 }
497
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900498 if ((c == '(' || c == '{') && opt == ParseExprOpt::FUNC) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900499 char cp = CloseParen(c);
500 if (terms && terms[0] == cp) {
501 paren_depth++;
502 save_paren = cp;
503 terms++;
504 } else if (cp == save_paren) {
505 paren_depth++;
506 }
507 continue;
508 }
509
510 if (c == save_paren) {
511 paren_depth--;
512 if (paren_depth == 0) {
513 terms--;
514 save_paren = 0;
515 }
516 }
517
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900518 if (c == '\\' && i + 1 < s.size() && opt != ParseExprOpt::COMMAND) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900519 char n = s[i+1];
520 if (n == '\\') {
521 i++;
522 continue;
523 }
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900524 if (n == '#' && ShouldHandleComments(opt)) {
Shinichiro Hamaji7fb82b02015-06-26 00:06:51 +0900525 r->AddValue(new Literal(s.substr(b, i-b)));
526 i++;
527 b = i;
528 continue;
529 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900530 if (n == '\r' || n == '\n') {
Shinichiro Hamajia0315fc2015-06-26 08:15:55 +0900531 if (terms && strchr(terms, ' ')) {
532 break;
533 }
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900534 if (i > b) {
Shinichiro Hamaji8f464582015-06-24 20:41:46 +0900535 r->AddValue(new Literal(TrimRightSpace(s.substr(b, i-b))));
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900536 }
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900537 r->AddValue(new Literal(StringPiece(" ")));
Dan Willemsenae8fc802015-08-20 13:46:14 -0700538 // Skip the current escaped newline
539 i += 2;
Shinichiro Hamaji3e98b6b2016-06-07 14:35:41 +0900540 if (n == '\r' && s.get(i) == '\n')
541 i++;
Dan Willemsenae8fc802015-08-20 13:46:14 -0700542 // Then continue skipping escaped newlines, spaces, and tabs
543 for (; i < s.size(); i++) {
544 if (s[i] == '\\' && (s.get(i+1) == '\r' || s.get(i+1) == '\n')) {
545 i++;
546 continue;
547 }
548 if (s[i] != ' ' && s[i] != '\t') {
Shinichiro Hamaji8f464582015-06-24 20:41:46 +0900549 break;
550 }
551 }
552 b = i;
553 i--;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900554 }
555 }
556 }
557
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900558 if (i > b) {
559 StringPiece rest = s.substr(b, i-b);
560 if (trim_right_space)
561 rest = TrimRightSpace(rest);
562 if (!rest.empty())
563 r->AddValue(new Literal(rest));
564 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900565 *index_out = i;
566 return r->Compact();
567}
568
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900569Value* ParseExpr(const Loc& loc, StringPiece s, ParseExprOpt opt) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900570 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900571 return ParseExprImpl(loc, s, NULL, opt, &n);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900572}
573
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900574string JoinValues(const vector<Value*>& vals, const char* sep) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900575 vector<string> val_strs;
576 for (Value* v : vals) {
577 val_strs.push_back(v->DebugString());
578 }
579 return JoinStrings(val_strs, sep);
580}
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900581
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900582Value* NewExpr2(Value* v1, Value* v2) {
583 Expr* e = new Expr();
584 e->AddValue(v1);
585 e->AddValue(v2);
586 return e;
587}
588
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900589Value* NewExpr3(Value* v1, Value* v2, Value* v3) {
590 Expr* e = new Expr();
591 e->AddValue(v1);
592 e->AddValue(v2);
593 e->AddValue(v3);
594 return e;
595}
596
Shinichiro Hamajib74b8902015-06-22 18:22:30 +0900597Value* NewLiteral(StringPiece s) {
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900598 return new Literal(s);
599}