blob: 3da740eb84089e80d9c68675d6ebb25f9d23ef6f [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 Hamaji347e06f2016-01-05 14:41:53 +090066
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090067 virtual string DebugString_() const override {
68 return s_.as_string();
69 }
70
71 private:
72 StringPiece s_;
73};
74
75class Expr : public Value {
76 public:
77 Expr() {
78 }
79
80 virtual ~Expr() {
81 for (Value* v : vals_) {
82 delete v;
83 }
84 }
85
86 // Takes the ownership of |v|.
87 void AddValue(Value* v) {
88 vals_.push_back(v);
89 }
90
91 virtual void Eval(Evaluator* ev, string* s) const override {
92 for (Value* v : vals_) {
93 v->Eval(ev, s);
94 }
95 }
96
97 virtual string DebugString_() const override {
98 string r;
99 for (Value* v : vals_) {
100 if (r.empty()) {
101 r += "Expr(";
102 } else {
103 r += ", ";
104 }
105 r += v->DebugString();
106 }
Shinichiro Hamajibaf2c382015-07-07 14:53:02 +0900107 if (!r.empty())
108 r += ")";
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900109 return r;
110 }
111
Shinichiro Hamaji4b351ab2016-02-12 19:42:30 +0900112 virtual Value* Compact() override {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900113 if (vals_.size() != 1) {
114 return this;
115 }
116 Value* r = vals_[0];
117 vals_.clear();
118 delete this;
119 return r;
120 }
121
122 private:
123 vector<Value*> vals_;
124};
125
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900126class SymRef : public Value {
127 public:
128 explicit SymRef(Symbol n)
129 : name_(n) {
130 }
131 virtual ~SymRef() {
132 }
133
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900134 virtual void Eval(Evaluator* ev, string* s) const override {
135 Var* v = ev->LookupVar(name_);
136 v->Eval(ev, s);
137 }
138
139 virtual string DebugString_() const override {
140 return StringPrintf("SymRef(%s)", name_.c_str());
141 }
142
143 private:
144 Symbol name_;
145};
146
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900147class VarRef : public Value {
148 public:
149 explicit VarRef(Value* n)
150 : name_(n) {
151 }
152 virtual ~VarRef() {
153 delete name_;
154 }
155
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900156 virtual void Eval(Evaluator* ev, string* s) const override {
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900157 ev->IncrementEvalDepth();
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900158 const string&& name = name_->Eval(ev);
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900159 ev->DecrementEvalDepth();
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900160 Var* v = ev->LookupVar(Intern(name));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900161 v->Eval(ev, s);
162 }
163
164 virtual string DebugString_() const override {
165 return StringPrintf("VarRef(%s)", name_->DebugString().c_str());
166 }
167
168 private:
169 Value* name_;
170};
171
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900172class VarSubst : public Value {
173 public:
174 explicit VarSubst(Value* n, Value* p, Value* s)
175 : name_(n), pat_(p), subst_(s) {
176 }
177 virtual ~VarSubst() {
178 delete name_;
179 delete pat_;
180 delete subst_;
181 }
182
183 virtual void Eval(Evaluator* ev, string* s) const override {
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900184 ev->IncrementEvalDepth();
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900185 const string&& name = name_->Eval(ev);
186 Var* v = ev->LookupVar(Intern(name));
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900187 const string&& pat_str = pat_->Eval(ev);
188 const string&& subst = subst_->Eval(ev);
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900189 ev->DecrementEvalDepth();
190 const string&& value = v->Eval(ev);
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +0900191 WordWriter ww(s);
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900192 Pattern pat(pat_str);
193 for (StringPiece tok : WordScanner(value)) {
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +0900194 ww.MaybeAddWhitespace();
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900195 pat.AppendSubstRef(tok, subst, s);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900196 }
197 }
198
199 virtual string DebugString_() const override {
200 return StringPrintf("VarSubst(%s:%s=%s)",
201 name_->DebugString().c_str(),
202 pat_->DebugString().c_str(),
203 subst_->DebugString().c_str());
204 }
205
206 private:
207 Value* name_;
208 Value* pat_;
209 Value* subst_;
210};
211
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900212class Func : public Value {
213 public:
214 explicit Func(FuncInfo* fi)
215 : fi_(fi) {
216 }
217
Shinichiro Hamajid0e188e2015-06-16 18:53:01 +0900218 ~Func() {
219 for (Value* a : args_)
220 delete a;
221 }
222
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900223 virtual void Eval(Evaluator* ev, string* s) const override {
224 LOG("Invoke func %s(%s)", name(), JoinValues(args_, ",").c_str());
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900225 ev->IncrementEvalDepth();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900226 fi_->func(args_, ev, s);
Shinichiro Hamaji28da2372015-11-30 19:03:53 +0900227 ev->DecrementEvalDepth();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900228 }
229
230 virtual string DebugString_() const override {
231 return StringPrintf("Func(%s %s)",
232 fi_->name,
233 JoinValues(args_, ",").c_str());
234 }
235
236 void AddArg(Value* v) {
237 args_.push_back(v);
238 }
239
240 const char* name() const { return fi_->name; }
241 int arity() const { return fi_->arity; }
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900242 int min_arity() const { return fi_->min_arity; }
243 bool trim_space() const { return fi_->trim_space; }
244 bool trim_right_space_1st() const { return fi_->trim_right_space_1st; }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900245
246 private:
247 FuncInfo* fi_;
248 vector<Value*> args_;
249};
250
251static char CloseParen(char c) {
252 switch (c) {
253 case '(':
254 return ')';
255 case '{':
256 return '}';
257 }
258 return 0;
259}
260
261static size_t SkipSpaces(StringPiece s, const char* terms) {
262 for (size_t i = 0; i < s.size(); i++) {
263 char c = s[i];
Shinichiro Hamaji64cf8912015-06-26 09:25:19 +0900264 if (strchr(terms, c))
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900265 return i;
Shinichiro Hamaji64cf8912015-06-26 09:25:19 +0900266 if (!isspace(c)) {
267 if (c != '\\')
268 return i;
269 char n = s.get(i + 1);
270 if (n != '\r' && n != '\n')
271 return i;
272 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900273 }
274 return s.size();
275}
276
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900277bool ShouldHandleComments(ParseExprOpt opt) {
278 return opt != ParseExprOpt::DEFINE && opt != ParseExprOpt::COMMAND;
279}
280
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900281void ParseFunc(const Loc& loc,
282 Func* f, StringPiece s, size_t i, char* terms,
283 size_t* index_out) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900284 terms[1] = ',';
285 terms[2] = '\0';
286 i += SkipSpaces(s.substr(i), terms);
287 if (i == s.size()) {
288 *index_out = i;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900289 return;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900290 }
291
292 int nargs = 1;
293 while (true) {
294 if (f->arity() && nargs >= f->arity()) {
295 terms[1] = '\0'; // Drop ','.
296 }
297
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900298 if (f->trim_space()) {
Shinichiro Hamajic8b4b1c2015-07-07 14:57:53 +0900299 for (; i < s.size(); i++) {
300 if (isspace(s[i]))
301 continue;
302 if (s[i] == '\\') {
303 char c = s.get(i+1);
304 if (c == '\r' || c == '\n')
305 continue;
306 }
307 break;
308 }
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900309 }
310 const bool trim_right_space = (f->trim_space() ||
311 (nargs == 1 && f->trim_right_space_1st()));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900312 size_t n;
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900313 Value* v = ParseExprImpl(loc, s.substr(i), terms, ParseExprOpt::FUNC,
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900314 &n, trim_right_space);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900315 // TODO: concatLine???
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900316 f->AddArg(v);
317 i += n;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900318 if (i == s.size()) {
319 ERROR("%s:%d: *** unterminated call to function '%s': "
320 "missing '%c'.",
321 LOCF(loc), f->name(), terms[0]);
322 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900323 nargs++;
324 if (s[i] == terms[0]) {
325 i++;
326 break;
327 }
328 i++; // Should be ','.
329 if (i == s.size())
330 break;
331 }
332
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900333 if (nargs <= f->min_arity()) {
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900334 ERROR("%s:%d: *** insufficient number of arguments (%d) to function `%s'.",
335 LOCF(loc), nargs - 1, f->name());
Shinichiro Hamaji81b2d0f2015-06-16 19:25:35 +0900336 }
337
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900338 *index_out = i;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900339 return;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900340}
341
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900342Value* ParseDollar(const Loc& loc, StringPiece s, size_t* index_out) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900343 CHECK(s.size() >= 2);
344 CHECK(s[0] == '$');
345 CHECK(s[1] != '$');
346
347 char cp = CloseParen(s[1]);
348 if (cp == 0) {
349 *index_out = 2;
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900350 return new SymRef(Intern(s.substr(1, 1)));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900351 }
352
353 char terms[] = {cp, ':', ' ', 0};
354 for (size_t i = 2;;) {
355 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900356 Value* vname = ParseExprImpl(loc, s.substr(i), terms,
357 ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900358 i += n;
359 if (s[i] == cp) {
360 *index_out = i + 1;
Shinichiro Hamaji347e06f2016-01-05 14:41:53 +0900361 if (vname->IsLiteral()) {
362 Literal* lit = static_cast<Literal*>(vname);
Shinichiro Hamaji82e20092015-11-17 15:18:28 +0900363 Symbol sym = Intern(lit->val());
364 if (g_flags.enable_kati_warnings) {
365 size_t found = sym.str().find_first_of(" ({");
366 if (found != string::npos) {
367 KATI_WARN("%s:%d: *warning*: variable lookup with '%c': %.*s",
368 loc, sym.str()[found], SPF(s));
369 }
370 }
371 Value* r = new SymRef(sym);
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900372 delete lit;
373 return r;
374 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900375 return new VarRef(vname);
376 }
377
Shinichiro Hamajia0315fc2015-06-26 08:15:55 +0900378 if (s[i] == ' ' || s[i] == '\\') {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900379 // ${func ...}
Shinichiro Hamaji347e06f2016-01-05 14:41:53 +0900380 if (vname->IsLiteral()) {
381 Literal* lit = static_cast<Literal*>(vname);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900382 if (FuncInfo* fi = GetFuncInfo(lit->val())) {
Shinichiro Hamajid0e188e2015-06-16 18:53:01 +0900383 delete lit;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900384 Func* func = new Func(fi);
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900385 ParseFunc(loc, func, s, i+1, terms, index_out);
386 return func;
Shinichiro Hamaji82e20092015-11-17 15:18:28 +0900387 } else {
388 KATI_WARN("%s:%d: *warning*: unknown make function '%.*s': %.*s",
389 loc, SPF(lit->val()), SPF(s));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900390 }
391 }
392
393 // Not a function. Drop ' ' from |terms| and parse it
394 // again. This is inefficient, but this code path should be
395 // rarely used.
396 delete vname;
397 terms[2] = 0;
398 i = 2;
399 continue;
400 }
401
402 if (s[i] == ':') {
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900403 terms[2] = '\0';
404 terms[1] = '=';
405 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900406 Value* pat = ParseExprImpl(loc, s.substr(i+1), terms,
407 ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900408 i += 1 + n;
409 if (s[i] == cp) {
410 Expr* v = new Expr;
411 v->AddValue(vname);
412 v->AddValue(new Literal(":"));
413 v->AddValue(pat);
Shinichiro Hamajif72e0242015-06-26 00:38:27 +0900414 *index_out = i + 1;
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900415 return new VarRef(v);
416 }
417
418 terms[1] = '\0';
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900419 Value* subst = ParseExprImpl(loc, s.substr(i+1), terms,
420 ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900421 i += 1 + n;
Shinichiro Hamajif72e0242015-06-26 00:38:27 +0900422 *index_out = i + 1;
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900423 return new VarSubst(vname->Compact(), pat, subst);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900424 }
425
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900426 // GNU make accepts expressions like $((). See unmatched_paren*.mk
427 // for detail.
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900428 size_t found = s.find(cp);
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900429 if (found != string::npos) {
Shinichiro Hamaji82e20092015-11-17 15:18:28 +0900430 KATI_WARN("%s:%d: *warning*: unmatched parentheses: %.*s",
431 loc, SPF(s));
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900432 *index_out = s.size();
433 return new SymRef(Intern(s.substr(2, found-2)));
434 }
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900435 ERROR("%s:%d: *** unterminated variable reference.", LOCF(loc));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900436 }
437}
438
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900439Value* ParseExprImpl(const Loc& loc,
440 StringPiece s, const char* terms, ParseExprOpt opt,
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900441 size_t* index_out, bool trim_right_space) {
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900442 if (s.get(s.size() - 1) == '\r')
443 s.remove_suffix(1);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900444
445 Expr* r = new Expr;
446 size_t b = 0;
447 char save_paren = 0;
448 int paren_depth = 0;
449 size_t i;
450 for (i = 0; i < s.size(); i++) {
451 char c = s[i];
Shinichiro Hamaji170e8b32015-09-15 15:36:57 +0900452 if (terms && strchr(terms, c) && !save_paren) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900453 break;
454 }
455
456 // Handle a comment.
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900457 if (!terms && c == '#' && ShouldHandleComments(opt)) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900458 if (i > b)
459 r->AddValue(new Literal(s.substr(b, i-b)));
460 bool was_backslash = false;
461 for (; i < s.size() && !(s[i] == '\n' && !was_backslash); i++) {
462 was_backslash = !was_backslash && s[i] == '\\';
463 }
464 *index_out = i;
465 return r->Compact();
466 }
467
468 if (c == '$') {
469 if (i + 1 >= s.size()) {
470 break;
471 }
472
473 if (i > b)
474 r->AddValue(new Literal(s.substr(b, i-b)));
475
476 if (s[i+1] == '$') {
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900477 r->AddValue(new Literal(StringPiece("$")));
Shinichiro Hamajib8a2bb12015-06-26 09:04:57 +0900478 i += 1;
479 b = i + 1;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900480 continue;
481 }
482
483 if (terms && strchr(terms, s[i+1])) {
484 *index_out = i + 1;
485 return r->Compact();
486 }
487
488 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900489 Value* v = ParseDollar(loc, s.substr(i), &n);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900490 i += n;
491 b = i;
492 i--;
493 r->AddValue(v);
494 continue;
495 }
496
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900497 if ((c == '(' || c == '{') && opt == ParseExprOpt::FUNC) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900498 char cp = CloseParen(c);
499 if (terms && terms[0] == cp) {
500 paren_depth++;
501 save_paren = cp;
502 terms++;
503 } else if (cp == save_paren) {
504 paren_depth++;
505 }
506 continue;
507 }
508
509 if (c == save_paren) {
510 paren_depth--;
511 if (paren_depth == 0) {
512 terms--;
513 save_paren = 0;
514 }
515 }
516
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900517 if (c == '\\' && i + 1 < s.size() && opt != ParseExprOpt::COMMAND) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900518 char n = s[i+1];
519 if (n == '\\') {
520 i++;
521 continue;
522 }
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900523 if (n == '#' && ShouldHandleComments(opt)) {
Shinichiro Hamaji7fb82b02015-06-26 00:06:51 +0900524 r->AddValue(new Literal(s.substr(b, i-b)));
525 i++;
526 b = i;
527 continue;
528 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900529 if (n == '\r' || n == '\n') {
Shinichiro Hamajia0315fc2015-06-26 08:15:55 +0900530 if (terms && strchr(terms, ' ')) {
531 break;
532 }
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900533 if (i > b) {
Shinichiro Hamaji8f464582015-06-24 20:41:46 +0900534 r->AddValue(new Literal(TrimRightSpace(s.substr(b, i-b))));
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900535 }
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900536 r->AddValue(new Literal(StringPiece(" ")));
Dan Willemsenae8fc802015-08-20 13:46:14 -0700537 // Skip the current escaped newline
538 i += 2;
539 // Then continue skipping escaped newlines, spaces, and tabs
540 for (; i < s.size(); i++) {
541 if (s[i] == '\\' && (s.get(i+1) == '\r' || s.get(i+1) == '\n')) {
542 i++;
543 continue;
544 }
545 if (s[i] != ' ' && s[i] != '\t') {
Shinichiro Hamaji8f464582015-06-24 20:41:46 +0900546 break;
547 }
548 }
549 b = i;
550 i--;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900551 }
552 }
553 }
554
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900555 if (i > b) {
556 StringPiece rest = s.substr(b, i-b);
557 if (trim_right_space)
558 rest = TrimRightSpace(rest);
559 if (!rest.empty())
560 r->AddValue(new Literal(rest));
561 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900562 *index_out = i;
563 return r->Compact();
564}
565
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900566Value* ParseExpr(const Loc& loc, StringPiece s, ParseExprOpt opt) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900567 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900568 return ParseExprImpl(loc, s, NULL, opt, &n);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900569}
570
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900571string JoinValues(const vector<Value*>& vals, const char* sep) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900572 vector<string> val_strs;
573 for (Value* v : vals) {
574 val_strs.push_back(v->DebugString());
575 }
576 return JoinStrings(val_strs, sep);
577}
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900578
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900579Value* NewExpr2(Value* v1, Value* v2) {
580 Expr* e = new Expr();
581 e->AddValue(v1);
582 e->AddValue(v2);
583 return e;
584}
585
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900586Value* NewExpr3(Value* v1, Value* v2, Value* v3) {
587 Expr* e = new Expr();
588 e->AddValue(v1);
589 e->AddValue(v2);
590 e->AddValue(v3);
591 return e;
592}
593
Shinichiro Hamajib74b8902015-06-22 18:22:30 +0900594Value* NewLiteral(StringPiece s) {
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900595 return new Literal(s);
596}