aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-11-04 08:44:03 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-11-04 09:26:17 +0200
commit63fe26fa228fab1286f8632efe5e93ce6960bfcb (patch)
tree286120e42f986ced04bb757327b5d2f1e1ff6138
parentb08b0075c1a9ac18fc848e5ed1f7d15582d313de (diff)
Add variable lookup hook to parser
-rw-r--r--build2/parser11
-rw-r--r--build2/parser.cxx87
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)
{