From 63fe26fa228fab1286f8632efe5e93ce6960bfcb Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 4 Nov 2016 08:44:03 +0200 Subject: Add variable lookup hook to parser --- build2/parser | 11 +++++-- build2/parser.cxx | 87 ++++++++++++++++++++++++++++++------------------------- 2 files changed, 57 insertions(+), 41 deletions(-) diff --git a/build2/parser b/build2/parser index bb6bc17..a5d39d3 100644 --- a/build2/parser +++ b/build2/parser @@ -91,12 +91,13 @@ namespace build2 if_else (token&, token_type&); void - variable (token&, token_type&, const variable_type&, token_type kind); + parse_variable (token&, token_type&, const variable_type&, token_type); string variable_name (names_type&&, const location&); - // Note: calls attributes_push() that the caller must pop. + // Note: calls attributes_push() that the caller must pop. Also expects + // the mode to auto-expire. // value variable_value (token&, token_type&, lexer_mode = lexer_mode::value); @@ -233,6 +234,12 @@ namespace build2 buildspec buildspec_clause (token&, token_type&, token_type end); + // Customization hooks. + // + protected: + virtual lookup + lookup_variable (name&& qual, string&& name, const location&); + // Utilities. // protected: diff --git a/build2/parser.cxx b/build2/parser.cxx index ba6b957..afe08b5 100644 --- a/build2/parser.cxx +++ b/build2/parser.cxx @@ -200,7 +200,7 @@ namespace build2 token t; type tt; - variable (t, tt, var, kind); + parse_variable (t, tt, var, kind); return t; } @@ -491,7 +491,7 @@ namespace build2 info << "consider changing to '.../*: " << var << "'"; enter_scope sg (*this, move (n.dir)); - variable (t, tt, var, att); + parse_variable (t, tt, var, att); } else { @@ -504,7 +504,7 @@ namespace build2 { name o (n.pair ? move (*++i) : name ()); enter_target tg (*this, move (n), move (o), nloc, trace); - variable (t, tt, var, att); + parse_variable (t, tt, var, att); } else { @@ -728,7 +728,7 @@ namespace build2 << "assigned in a scope" << info << "consider changing to '*: " << var << "'"; - variable (t, tt, var, tt); + parse_variable (t, tt, var, tt); if (tt == type::newline) next (t, tt); @@ -1455,7 +1455,7 @@ namespace build2 } void parser:: - variable (token& t, type& tt, const variable_type& var, type kind) + parse_variable (token& t, type& tt, const variable_type& var, type kind) { value rhs (variable_value (t, tt)); @@ -2344,43 +2344,10 @@ namespace build2 { // Variable expansion. // - - // Process variable name. - // - if (name.front () == '.') // Fully qualified name. - name.erase (0, 1); - else - { - //@@ TODO: append namespace if any. - } - - // If we are qualified, it can be a scope or a target. - // - enter_scope sg; - enter_target tg; - - if (qual.directory ()) //@@ OUT - sg = enter_scope (*this, move (qual.dir)); - else if (!qual.empty ()) - // @@ OUT TODO - // - tg = enter_target ( - *this, move (qual), build2::name (), loc, trace); - - // Lookup. - // - const auto& var (var_pool.insert (move (name))); - auto l (target_ != nullptr ? (*target_)[var] : (*scope_)[var]); + lookup l (lookup_variable (move (qual), move (name), loc)); if (!l) { - // Undefined/NULL namespace variables are not allowed. - // - // @@ TMP this isn't proving to be particularly useful. - // - //if (var.name.find ('.') != string::npos) - //fail (loc) << "undefined/null namespace variable " << var; - // See if we should set the NULL indicator. // if (set_null ()) @@ -2935,6 +2902,48 @@ namespace build2 return bs; } + lookup parser:: + lookup_variable (name&& qual, string&& name, const location& loc) + { + tracer trace ("parser::lookup_variable", &path_); + + // Process variable name. + // + if (name.front () == '.') // Fully namespace-qualified name. + name.erase (0, 1); + else + { + //@@ TODO: append namespace if any. + } + + // If we are qualified, it can be a scope or a target. + // + enter_scope sg; + enter_target tg; + + if (qual.directory ()) //@@ OUT + sg = enter_scope (*this, move (qual.dir)); + else if (!qual.empty ()) + // @@ OUT TODO + // + tg = enter_target (*this, move (qual), build2::name (), loc, trace); + + // Lookup. + // + const auto& var (var_pool.insert (move (name))); + return target_ != nullptr ? (*target_)[var] : (*scope_)[var]; + + // Undefined/NULL namespace variables are not allowed. + // + // @@ TMP this isn't proving to be particularly useful. + // + // if (!l) + // { + // if (var.name.find ('.') != string::npos) + // fail (loc) << "undefined/null namespace variable " << var; + // } + } + void parser:: switch_scope (const dir_path& p) { -- cgit v1.1