From ae20570f2ad55b2fa8e71cf450457cb9c4b21b1b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 18 Apr 2016 10:17:37 +0200 Subject: Add support for using value attributes in eval context For example: if ($x == [null]) Or: if ([uint64] 01 == [uint64] 1) --- build2/parser | 78 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 22 deletions(-) (limited to 'build2/parser') diff --git a/build2/parser b/build2/parser index ced81c3..0962348 100644 --- a/build2/parser +++ b/build2/parser @@ -5,6 +5,8 @@ #ifndef BUILD2_PARSER #define BUILD2_PARSER +#include + #include #include @@ -87,31 +89,61 @@ namespace build2 string variable_name (names_type&&, const location&); - pair // See names_null() return type. + // Note: calls attributes_push() that the caller must pop. + // + value variable_value (token&, token_type&); void variable_attributes (const variable_type&); void - value_attributes (const variable_type&, + value_attributes (const variable_type*, // Optional. value& lhs, - pair&& rhs, + value&& rhs, token_type kind); - pair // See names_null() return type. + value eval (token&, token_type&); - bool - eval_trailer (token&, token_type&, names_type&); + value + eval_trailer (token&, token_type&); - // If the next token is '[' parse the attribute sequence until ']' storing - // the result in the ha_/as_/al_ members (which are only valid until the - // next call). Then get the next token and, if standalone is false, verify - // it is not newline/eos (i.e., there is something after it). Return ha_. + // Attributes stack. We can have nested attributes, for example: // - bool - attributes (token&, token_type&, bool standalone = false); + // x = [bool] ([uint64] $x == [uint64] $y) + // + // In this example we only apply the value attributes after evaluating + // the context, which has its own attributes. + // + struct attributes + { + bool has; // Has attributes flag. + location loc; // Start of attributes location. + vector> ats; // Attributes. + + explicit operator bool () const {return has;} + }; + + // Push a new entry into the attributes_ stack. If the next token is '[' + // parse the attribute sequence until ']' setting the 'has' flag and + // storing the result on the stack. Then get the next token and, if + // standalone is false, verify it is not newline/eos (i.e., there is + // something after it). Return the top of the stack. + // + attributes& + attributes_push (token&, token_type&, bool standalone = false); + + attributes + attributes_pop () + { + attributes r (move (attributes_.top ())); + attributes_.pop (); + return r; + } + + attributes& + attributes_top () {return attributes_.top ();} // If chunk is true, then parse the smallest but complete, name-wise, // chunk of input. Note that in this case you may still end up with @@ -125,18 +157,22 @@ namespace build2 return ns; } - // As above but also indicate if the value is NOT NULL. The only way for - // the value to be NULL is if it is the result of a sole, unquoted - // variable expansion, function call, or context evaluation. + // As above but return the result as a value (always untyped) indicating + // if it is NULL. The only way for the value to be NULL is if it is the + // result of a sole, unquoted variable expansion, function call, or + // context evaluation. // - pair - names_null (token& t, token_type& tt) + value + names_value (token& t, token_type& tt) { names_type ns; - bool n (names (t, tt, ns, false, 0, nullptr, nullptr, nullptr)); - return make_pair (move (ns), n); + return names (t, tt, ns, false, 0, nullptr, nullptr, nullptr) + ? value (move (ns)) + : value (nullptr); } + // Return true if the parsed value is NOT NULL. + // bool names (token& t, token_type& tt, names_type& ns, bool chunk = false) { @@ -321,9 +357,7 @@ namespace build2 scope* scope_; // Current base scope (out_base). scope* root_; // Current root scope (out_root). - bool ha_; // Has attributes flag. - location al_; // Current attributes location. - vector> as_; // Current attributes. + std::stack attributes_; target* default_target_; names_type export_value_; -- cgit v1.1