summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/parsers.cc17
-rw-r--r--src/parsers.h4
-rw-r--r--src/parsers_test.cc5
3 files changed, 20 insertions, 6 deletions
diff --git a/src/parsers.cc b/src/parsers.cc
index 8408195..4f19046 100644
--- a/src/parsers.cc
+++ b/src/parsers.cc
@@ -254,7 +254,7 @@ bool ManifestParser::Parse(const string& input, string* err) {
break;
case Token::IDENT: {
string name, value;
- if (!ParseLet(&name, &value, err))
+ if (!ParseLet(&name, &value, true, err))
return false;
if (value.substr(0, 9) == "ROOT_HACK") {
// XXX remove this hack, or make it more principled.
@@ -302,7 +302,7 @@ bool ManifestParser::ParseRule(string* err) {
while (tokenizer_.PeekToken() != Token::OUTDENT) {
string key, val;
- if (!ParseLet(&key, &val, err))
+ if (!ParseLet(&key, &val, false, err))
return false;
string parse_err;
@@ -331,7 +331,8 @@ bool ManifestParser::ParseRule(string* err) {
return true;
}
-bool ManifestParser::ParseLet(string* name, string* value, string* err) {
+bool ManifestParser::ParseLet(string* name, string* value, bool expand,
+ string* err) {
if (!tokenizer_.ReadIdent(name))
return tokenizer_.Error("expected variable name", err);
if (!tokenizer_.ExpectToken(Token::EQUALS, err))
@@ -342,6 +343,14 @@ bool ManifestParser::ParseLet(string* name, string* value, string* err) {
if (!tokenizer_.ReadToNewline(value, err))
return false;
+ if (expand) {
+ EvalString eval;
+ string eval_err;
+ if (!eval.Parse(*value, &eval_err))
+ return tokenizer_.Error(eval_err, err);
+ *value = eval.Evaluate(env_);
+ }
+
return true;
}
@@ -427,7 +436,7 @@ bool ManifestParser::ParseEdge(string* err) {
env->parent_ = env_;
while (tokenizer_.PeekToken() != Token::OUTDENT) {
string key, val;
- if (!ParseLet(&key, &val, err))
+ if (!ParseLet(&key, &val, false, err))
return false;
env->AddBinding(key, val);
}
diff --git a/src/parsers.h b/src/parsers.h
index 2655ce8..fc09cce 100644
--- a/src/parsers.h
+++ b/src/parsers.h
@@ -83,7 +83,9 @@ struct ManifestParser {
bool Parse(const string& input, string* err);
bool ParseRule(string* err);
- bool ParseLet(string* key, string* val, string* err);
+ // Parse a key=val statement. If expand is true, evaluate variables
+ // within the value immediately.
+ bool ParseLet(string* key, string* val, bool expand, string* err);
bool ParseEdge(string* err);
bool ParseSubNinja(string* err);
diff --git a/src/parsers_test.cc b/src/parsers_test.cc
index 8187a62..58e40b8 100644
--- a/src/parsers_test.cc
+++ b/src/parsers_test.cc
@@ -57,12 +57,15 @@ TEST_F(ParserTest, Variables) {
"\n"
"extra = -pthread\n"
"with_under = -under\n"
-"build a: link b c\n"));
+"build a: link b c\n"
+"nested1 = 1\n"
+"nested2 = $nested1/2\n"));
ASSERT_EQ(1, state.edges_.size());
Edge* edge = state.edges_[0];
EXPECT_EQ("ld one-letter-test -pthread -under -o a b c",
edge->EvaluateCommand());
+ EXPECT_EQ("1/2", state.bindings_.LookupVariable("nested2"));
}
TEST_F(ParserTest, VariableScope) {