diff options
author | Evan Martin <martine@danga.com> | 2010-12-20 00:19:34 (GMT) |
---|---|---|
committer | Evan Martin <martine@danga.com> | 2010-12-21 00:01:53 (GMT) |
commit | f2a4bac9127124563cd783a798e64dd15204d598 (patch) | |
tree | 83d8283883197d41146a19beded31f5fb179ab2b | |
parent | 1297efdd10db66a6174f4fa2e71dd4169b278abd (diff) | |
download | Ninja-f2a4bac9127124563cd783a798e64dd15204d598.zip Ninja-f2a4bac9127124563cd783a798e64dd15204d598.tar.gz Ninja-f2a4bac9127124563cd783a798e64dd15204d598.tar.bz2 |
immediately evaluate variables in top-level bindings
-rw-r--r-- | src/parsers.cc | 17 | ||||
-rw-r--r-- | src/parsers.h | 4 | ||||
-rw-r--r-- | src/parsers_test.cc | 5 |
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) { |