blob: 87cc7368ff6b15e503176c6a05cb03d8249c78c4 [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 "value.h"
18
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
34shared_ptr<string> Evaluable::Eval(Evaluator* ev) const {
35 shared_ptr<string> s = make_shared<string>();
36 Eval(ev, s.get());
37 return s;
38}
39
40Value::Value() {
41}
42
43Value::~Value() {
44}
45
46string Value::DebugString() const {
47 if (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
65 virtual string DebugString_() const override {
66 return s_.as_string();
67 }
68
69 private:
70 StringPiece s_;
71};
72
73class Expr : public Value {
74 public:
75 Expr() {
76 }
77
78 virtual ~Expr() {
79 for (Value* v : vals_) {
80 delete v;
81 }
82 }
83
84 // Takes the ownership of |v|.
85 void AddValue(Value* v) {
86 vals_.push_back(v);
87 }
88
89 virtual void Eval(Evaluator* ev, string* s) const override {
90 for (Value* v : vals_) {
91 v->Eval(ev, s);
92 }
93 }
94
95 virtual string DebugString_() const override {
96 string r;
97 for (Value* v : vals_) {
98 if (r.empty()) {
99 r += "Expr(";
100 } else {
101 r += ", ";
102 }
103 r += v->DebugString();
104 }
105 r += ")";
106 return r;
107 }
108
109 virtual Value* Compact() {
110 if (vals_.size() != 1) {
111 return this;
112 }
113 Value* r = vals_[0];
114 vals_.clear();
115 delete this;
116 return r;
117 }
118
119 private:
120 vector<Value*> vals_;
121};
122
123class VarRef : public Value {
124 public:
125 explicit VarRef(Value* n)
126 : name_(n) {
127 }
128 virtual ~VarRef() {
129 delete name_;
130 }
131
132 virtual shared_ptr<string> Eval(Evaluator* ev) const override {
133 shared_ptr<string> name = name_->Eval(ev);
134 Var* v = ev->LookupVar(*name);
135 return v->Eval(ev);
136 }
137
138 virtual void Eval(Evaluator* ev, string* s) const override {
139 shared_ptr<string> name = name_->Eval(ev);
140 Var* v = ev->LookupVar(*name);
141 v->Eval(ev, s);
142 }
143
144 virtual string DebugString_() const override {
145 return StringPrintf("VarRef(%s)", name_->DebugString().c_str());
146 }
147
148 private:
149 Value* name_;
150};
151
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900152class VarSubst : public Value {
153 public:
154 explicit VarSubst(Value* n, Value* p, Value* s)
155 : name_(n), pat_(p), subst_(s) {
156 }
157 virtual ~VarSubst() {
158 delete name_;
159 delete pat_;
160 delete subst_;
161 }
162
163 virtual void Eval(Evaluator* ev, string* s) const override {
164 shared_ptr<string> name = name_->Eval(ev);
165 Var* v = ev->LookupVar(*name);
166 shared_ptr<string> value = v->Eval(ev);
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +0900167 shared_ptr<string> pat_str = pat_->Eval(ev);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900168 shared_ptr<string> subst = subst_->Eval(ev);
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +0900169 WordWriter ww(s);
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +0900170 Pattern pat(*pat_str);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900171 for (StringPiece tok : WordScanner(*value)) {
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +0900172 ww.MaybeAddWhitespace();
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +0900173 pat.AppendSubstRef(tok, *subst, s);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900174 }
175 }
176
177 virtual string DebugString_() const override {
178 return StringPrintf("VarSubst(%s:%s=%s)",
179 name_->DebugString().c_str(),
180 pat_->DebugString().c_str(),
181 subst_->DebugString().c_str());
182 }
183
184 private:
185 Value* name_;
186 Value* pat_;
187 Value* subst_;
188};
189
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900190class Func : public Value {
191 public:
192 explicit Func(FuncInfo* fi)
193 : fi_(fi) {
194 }
195
Shinichiro Hamajid0e188e2015-06-16 18:53:01 +0900196 ~Func() {
197 for (Value* a : args_)
198 delete a;
199 }
200
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900201 virtual void Eval(Evaluator* ev, string* s) const override {
202 LOG("Invoke func %s(%s)", name(), JoinValues(args_, ",").c_str());
203 fi_->func(args_, ev, s);
204 }
205
206 virtual string DebugString_() const override {
207 return StringPrintf("Func(%s %s)",
208 fi_->name,
209 JoinValues(args_, ",").c_str());
210 }
211
212 void AddArg(Value* v) {
213 args_.push_back(v);
214 }
215
216 const char* name() const { return fi_->name; }
217 int arity() const { return fi_->arity; }
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900218 int min_arity() const { return fi_->min_arity; }
219 bool trim_space() const { return fi_->trim_space; }
220 bool trim_right_space_1st() const { return fi_->trim_right_space_1st; }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900221
222 private:
223 FuncInfo* fi_;
224 vector<Value*> args_;
225};
226
227static char CloseParen(char c) {
228 switch (c) {
229 case '(':
230 return ')';
231 case '{':
232 return '}';
233 }
234 return 0;
235}
236
237static size_t SkipSpaces(StringPiece s, const char* terms) {
238 for (size_t i = 0; i < s.size(); i++) {
239 char c = s[i];
240 if ((c != ' ' && c != '\t') || strchr(terms, c))
241 return i;
242 }
243 return s.size();
244}
245
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900246Value* ParseFunc(Func* f, StringPiece s, size_t i, char* terms,
247 size_t* index_out) {
248 terms[1] = ',';
249 terms[2] = '\0';
250 i += SkipSpaces(s.substr(i), terms);
251 if (i == s.size()) {
252 *index_out = i;
253 return f;
254 }
255
256 int nargs = 1;
257 while (true) {
258 if (f->arity() && nargs >= f->arity()) {
259 terms[1] = '\0'; // Drop ','.
260 }
261
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900262 if (f->trim_space()) {
263 while (i < s.size() && isspace(s[i]))
264 i++;
265 }
266 const bool trim_right_space = (f->trim_space() ||
267 (nargs == 1 && f->trim_right_space_1st()));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900268 size_t n;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900269 Value* v = ParseExprImpl(s.substr(i), terms, ParseExprOpt::NORMAL,
270 &n, trim_right_space);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900271 // TODO: concatLine???
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900272 f->AddArg(v);
273 i += n;
274 nargs++;
275 if (s[i] == terms[0]) {
276 i++;
277 break;
278 }
279 i++; // Should be ','.
280 if (i == s.size())
281 break;
282 }
283
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900284 if (nargs <= f->min_arity()) {
Shinichiro Hamaji81b2d0f2015-06-16 19:25:35 +0900285 // TODO: Show filename and line number.
286 ERROR("*** insufficient number of arguments (%d) to function `%s'.",
287 nargs - 1, f->name());
288 }
289
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900290 *index_out = i;
291 return f;
292}
293
294Value* ParseDollar(StringPiece s, size_t* index_out) {
295 CHECK(s.size() >= 2);
296 CHECK(s[0] == '$');
297 CHECK(s[1] != '$');
298
299 char cp = CloseParen(s[1]);
300 if (cp == 0) {
301 *index_out = 2;
302 return new VarRef(new Literal(s.substr(1, 1)));
303 }
304
305 char terms[] = {cp, ':', ' ', 0};
306 for (size_t i = 2;;) {
307 size_t n;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900308 Value* vname = ParseExprImpl(s.substr(i), terms, ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900309 i += n;
310 if (s[i] == cp) {
311 *index_out = i + 1;
312 return new VarRef(vname);
313 }
314
315 if (s[i] == ' ') {
316 // ${func ...}
317 if (Literal* lit = reinterpret_cast<Literal*>(vname)) {
318 if (FuncInfo* fi = GetFuncInfo(lit->val())) {
Shinichiro Hamajid0e188e2015-06-16 18:53:01 +0900319 delete lit;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900320 Func* func = new Func(fi);
321 return ParseFunc(func, s, i+1, terms, index_out);
322 }
323 }
324
325 // Not a function. Drop ' ' from |terms| and parse it
326 // again. This is inefficient, but this code path should be
327 // rarely used.
328 delete vname;
329 terms[2] = 0;
330 i = 2;
331 continue;
332 }
333
334 if (s[i] == ':') {
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900335 terms[2] = '\0';
336 terms[1] = '=';
337 size_t n;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900338 Value* pat = ParseExprImpl(s.substr(i+1), terms, ParseExprOpt::NORMAL,
339 &n);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900340 i += 1 + n;
341 if (s[i] == cp) {
342 Expr* v = new Expr;
343 v->AddValue(vname);
344 v->AddValue(new Literal(":"));
345 v->AddValue(pat);
346 return new VarRef(v);
347 }
348
349 terms[1] = '\0';
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900350 Value* subst = ParseExprImpl(s.substr(i+1), terms, ParseExprOpt::NORMAL,
351 &n);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900352 i += 1 + n;
353 return new VarSubst(vname->Compact(), pat, subst);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900354 }
355
356 CHECK(false);
357 }
358}
359
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900360Value* ParseExprImpl(StringPiece s, const char* terms, ParseExprOpt opt,
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900361 size_t* index_out, bool trim_right_space) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900362 // TODO: A faulty optimization.
363#if 0
364 char specials[] = "$(){}\\\n";
365 size_t found = s.find_first_of(specials);
366 if (found == string::npos) {
367 *index_out = s.size();
368 return new Literal(s);
369 }
370 if (terms && strchr(terms, s[found])) {
371 *index_out = found;
372 return new Literal(s.substr(0, found));
373 }
374#endif
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900375 if (s.get(s.size() - 1) == '\r')
376 s.remove_suffix(1);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900377
378 Expr* r = new Expr;
379 size_t b = 0;
380 char save_paren = 0;
381 int paren_depth = 0;
382 size_t i;
383 for (i = 0; i < s.size(); i++) {
384 char c = s[i];
385 if (terms && strchr(terms, c)) {
386 break;
387 }
388
389 // Handle a comment.
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900390 if (!terms && c == '#' && opt == ParseExprOpt::NORMAL) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900391 if (i > b)
392 r->AddValue(new Literal(s.substr(b, i-b)));
393 bool was_backslash = false;
394 for (; i < s.size() && !(s[i] == '\n' && !was_backslash); i++) {
395 was_backslash = !was_backslash && s[i] == '\\';
396 }
397 *index_out = i;
398 return r->Compact();
399 }
400
401 if (c == '$') {
402 if (i + 1 >= s.size()) {
403 break;
404 }
405
406 if (i > b)
407 r->AddValue(new Literal(s.substr(b, i-b)));
408
409 if (s[i+1] == '$') {
410 r->AddValue(new Literal(STRING_PIECE("$")));
411 i += 2;
412 b = i;
413 continue;
414 }
415
416 if (terms && strchr(terms, s[i+1])) {
417 *index_out = i + 1;
418 return r->Compact();
419 }
420
421 size_t n;
422 Value* v = ParseDollar(s.substr(i), &n);
423 i += n;
424 b = i;
425 i--;
426 r->AddValue(v);
427 continue;
428 }
429
430 if (c == '(' || c == '{') {
431 char cp = CloseParen(c);
432 if (terms && terms[0] == cp) {
433 paren_depth++;
434 save_paren = cp;
435 terms++;
436 } else if (cp == save_paren) {
437 paren_depth++;
438 }
439 continue;
440 }
441
442 if (c == save_paren) {
443 paren_depth--;
444 if (paren_depth == 0) {
445 terms--;
446 save_paren = 0;
447 }
448 }
449
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900450 if (c == '\\' && i + 1 < s.size() && opt != ParseExprOpt::COMMAND) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900451 char n = s[i+1];
452 if (n == '\\') {
453 i++;
454 continue;
455 }
456 if (n == '\r' || n == '\n') {
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900457 if (i > b) {
458 r->AddValue(new Literal(s.substr(b, i-b)));
459 }
460 r->AddValue(new Literal(STRING_PIECE(" ")));
461 i++;
462 if (n == '\r' && s.get(i+1) == '\n')
463 i++;
464 b = i + 1;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900465 }
466 }
467 }
468
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900469 if (i > b) {
470 StringPiece rest = s.substr(b, i-b);
471 if (trim_right_space)
472 rest = TrimRightSpace(rest);
473 if (!rest.empty())
474 r->AddValue(new Literal(rest));
475 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900476 *index_out = i;
477 return r->Compact();
478}
479
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900480Value* ParseExpr(StringPiece s, ParseExprOpt opt) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900481 size_t n;
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900482 return ParseExprImpl(s, NULL, opt, &n);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900483}
484
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900485Value* ParseExprUntilComma(StringPiece s, size_t* index_out) {
486 char terms[] = {',', '\0'};
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900487 return ParseExprImpl(s, terms, ParseExprOpt::NORMAL, index_out);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900488}
489
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900490string JoinValues(const vector<Value*>& vals, const char* sep) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900491 vector<string> val_strs;
492 for (Value* v : vals) {
493 val_strs.push_back(v->DebugString());
494 }
495 return JoinStrings(val_strs, sep);
496}
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900497
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900498Value* NewExpr2(Value* v1, Value* v2) {
499 Expr* e = new Expr();
500 e->AddValue(v1);
501 e->AddValue(v2);
502 return e;
503}
504
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900505Value* NewExpr3(Value* v1, Value* v2, Value* v3) {
506 Expr* e = new Expr();
507 e->AddValue(v1);
508 e->AddValue(v2);
509 e->AddValue(v3);
510 return e;
511}
512
Shinichiro Hamajib74b8902015-06-22 18:22:30 +0900513Value* NewLiteral(StringPiece s) {
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900514 return new Literal(s);
515}