diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-03-30 14:16:54 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-03-30 14:16:54 +0200 |
commit | b1715878d50aa8a3c3e2404f3ded120329994aba (patch) | |
tree | 85c9feb4556f7555f0acc0e2d012ee52b73c1b34 /build/parser.cxx | |
parent | 70256514a09e4692c6839f5c2b21b7ec9c1055bd (diff) |
Initial support for command line variables
Diffstat (limited to 'build/parser.cxx')
-rw-r--r-- | build/parser.cxx | 156 |
1 files changed, 74 insertions, 82 deletions
diff --git a/build/parser.cxx b/build/parser.cxx index 617f22b..e2b11f0 100644 --- a/build/parser.cxx +++ b/build/parser.cxx @@ -27,11 +27,6 @@ using namespace std; namespace build { - // Output the token type and value in a format suitable for diagnostics. - // - ostream& - operator<< (ostream&, const token&); - static location get_location (const token&, const void*); @@ -70,6 +65,21 @@ namespace build process_default_target (t); } + token parser:: + parse_variable (lexer& l, scope& s, string name, token_type kind) + { + path_ = &l.name (); + lexer_ = &l; + scope_ = &s; + + token t (type::eos, false, 0, 0); + type tt; + next (t, tt); + + variable (t, tt, name, kind); + return t; + } + void parser:: clause (token& t, token_type& tt) { @@ -305,21 +315,11 @@ namespace build // if (tt == type::equal || tt == type::plus_equal) { - bool assign (tt == type::equal); - // LHS should be a single, simple name. // if (ns.size () != 1 || !ns[0].type.empty () || !ns[0].dir.empty ()) fail (t) << "variable name expected before " << t; - next (t, tt); - - names_type vns (tt != type::newline && tt != type::eos - ? names (t, tt) - : names_type ()); - - // Enter the variable. - // string name; if (ns[0].value.front () == '.') // Fully qualified name. name.assign (ns[0].value, 1, string::npos); @@ -327,48 +327,9 @@ namespace build //@@ TODO: append namespace if any. name = move (ns[0].value); - const variable& var (variable_pool.find (move (name))); - - if (assign) - { - value_ptr& val (scope_->variables[var]); - - if (val == nullptr) // Initialization. - { - val.reset (new list_value (*scope_, move (vns))); - } - else // Assignment. - { - //@@ TODO: assuming it is a list. - // - dynamic_cast<list_value&> (*val).data = move (vns); - } - } - else - { - if (auto val = (*scope_)[var]) - { - //@@ TODO: assuming it is a list. - // - list_value* lv (&val.as<list_value&> ()); - - if (&lv->scope != scope_) // Append to value from parent scope? - { - list_value_ptr nval (new list_value (*scope_, lv->data)); - lv = nval.get (); // Append to. - scope_->variables.emplace (var, move (nval)); - } - - lv->data.insert (lv->data.end (), - make_move_iterator (vns.begin ()), - make_move_iterator (vns.end ())); - } - else // Initialization. - { - list_value_ptr nval (new list_value (*scope_, move (vns))); - scope_->variables.emplace (var, move (nval)); - } - } + type kind (tt); + next (t, tt); + variable (t, tt, move (name), kind); if (tt == type::newline) next (t, tt); @@ -648,6 +609,61 @@ namespace build } void parser:: + variable (token& t, token_type& tt, string name, token_type kind) + { + bool assign (kind == type::equal); + + names_type vns (tt != type::newline && tt != type::eos + ? names (t, tt) + : names_type ()); + + // Enter the variable. + // + const auto& var (variable_pool.find (move (name))); + + if (assign) + { + value_ptr& val (scope_->variables[var]); + + if (val == nullptr) // Initialization. + { + val.reset (new list_value (*scope_, move (vns))); + } + else // Assignment. + { + //@@ TODO: assuming it is a list. + // + dynamic_cast<list_value&> (*val).data = move (vns); + } + } + else + { + if (auto val = (*scope_)[var]) + { + //@@ TODO: assuming it is a list. + // + list_value* lv (&val.as<list_value&> ()); + + if (&lv->scope != scope_) // Append to value from parent scope? + { + list_value_ptr nval (new list_value (*scope_, lv->data)); + lv = nval.get (); // Append to. + scope_->variables.emplace (var, move (nval)); + } + + lv->data.insert (lv->data.end (), + make_move_iterator (vns.begin ()), + make_move_iterator (vns.end ())); + } + else // Initialization. + { + list_value_ptr nval (new list_value (*scope_, move (vns))); + scope_->variables.emplace (var, move (nval)); + } + } + } + + void parser:: names (token& t, type& tt, names_type& ns, @@ -830,7 +846,7 @@ namespace build //@@ TODO: append namespace if any. n = t.name (); - const variable& var (variable_pool.find (move (n))); + const auto& var (variable_pool.find (move (n))); auto val ((*scope_)[var]); // Undefined namespaces variables are not allowed. @@ -1289,28 +1305,4 @@ namespace build const string& p (**static_cast<const string* const*> (data)); return location (p.c_str (), t.line (), t.column ()); } - - // Output the token type and value in a format suitable for diagnostics. - // - ostream& - operator<< (ostream& os, const token& t) - { - switch (t.type ()) - { - case token_type::eos: os << "<end-of-file>"; break; - case token_type::newline: os << "<newline>"; break; - case token_type::pair_separator: os << "<pair separator>"; break; - case token_type::colon: os << ":"; break; - case token_type::lcbrace: os << "{"; break; - case token_type::rcbrace: os << "}"; break; - case token_type::equal: os << "="; break; - case token_type::plus_equal: os << "+="; break; - case token_type::dollar: os << "$"; break; - case token_type::lparen: os << "("; break; - case token_type::rparen: os << ")"; break; - case token_type::name: os << t.name (); break; - } - - return os; - } } |