From ce29e3d72ded432b9ac9354ac92c588142de9b89 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 20 Mar 2020 08:40:59 +0200 Subject: Lexer support for default value assignment (?=) Note: not yet supported in the parser. --- libbuild2/lexer+normal.test.testscript | 36 ++++++++++++++++++++++++++++++++++ libbuild2/lexer.cxx | 23 ++++++++++++++++------ libbuild2/parser.cxx | 10 ++++++++++ libbuild2/token.cxx | 1 + libbuild2/token.hxx | 1 + 5 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 libbuild2/lexer+normal.test.testscript diff --git a/libbuild2/lexer+normal.test.testscript b/libbuild2/lexer+normal.test.testscript new file mode 100644 index 0000000..c9448c3 --- /dev/null +++ b/libbuild2/lexer+normal.test.testscript @@ -0,0 +1,36 @@ +# file : libbuild2/lexer+normal.test.testscript +# license : MIT; see accompanying LICENSE file + +test.arguments = normal + +: assign +: +$* <:'x=y' >>EOO +'x' += +'y' +EOO + +: append +: +$* <:'x+=y' >>EOO +'x' ++= +'y' +EOO + +: prepend +: +$* <:'x=+y' >>EOO +'x' +=+ +'y' +EOO + +: default-assign +: +$* <:'x?=y' >>EOO +'x' +?= +'y' +EOO diff --git a/libbuild2/lexer.cxx b/libbuild2/lexer.cxx index 9989d1e..5ffac54 100644 --- a/libbuild2/lexer.cxx +++ b/libbuild2/lexer.cxx @@ -43,8 +43,8 @@ namespace build2 case lexer_mode::normal: { a = true; - s1 = ":<>=+ $(){}#\t\n"; - s2 = " = "; + s1 = ":<>=+? $(){}#\t\n"; + s2 = " == "; break; } case lexer_mode::value: @@ -182,6 +182,8 @@ namespace build2 // NOTE: remember to update mode(), next_eval() if adding any new special // characters. + // These are special in all the modes handled by this function. + // switch (c) { case '\n': @@ -248,11 +250,10 @@ namespace build2 } } - // The following characters are special in the normal, variable, and + // The following characters are special in the normal and // switch_expressions modes. // if (m == lexer_mode::normal || - m == lexer_mode::variable || m == lexer_mode::switch_expressions || m == lexer_mode::case_patterns) { @@ -262,9 +263,9 @@ namespace build2 } } - // The following characters are special in the normal and variable modes. + // The following characters are special in the normal mode. // - if (m == lexer_mode::normal || m == lexer_mode::variable) + if (m == lexer_mode::normal) { switch (c) { @@ -285,6 +286,16 @@ namespace build2 get (); return make_token (type::append); } + break; + } + case '?': + { + if (peek () == '=') + { + get (); + return make_token (type::default_assign); + } + break; } } } diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index 91f2d5c..ec5e161 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -2749,6 +2749,16 @@ namespace build2 void parser:: parse_variable (token& t, type& tt, const variable& var, type kind) { + // @@ TODO: yet unclear what should the logic be here: we could expect + // the called to handle skipping or skip it here. Need to see how + // everything fits. + // + // Note that here we treat default assignment (?=) the same as normal + // assignment expecting the caller to check whether the assignment is + // necessary (and skipping evaluating the value altogether otherwise). + // + assert (kind != type::default_assign); + value rhs (parse_variable_value (t, tt)); value& lhs ( diff --git a/libbuild2/token.cxx b/libbuild2/token.cxx index 0f9a189..4975a02 100644 --- a/libbuild2/token.cxx +++ b/libbuild2/token.cxx @@ -41,6 +41,7 @@ namespace build2 case token_type::assign: os << q << '=' << q; break; case token_type::prepend: os << q << "=+" << q; break; case token_type::append: os << q << "+=" << q; break; + case token_type::default_assign: os << q << "?=" << q; break; case token_type::equal: os << q << "==" << q; break; case token_type::not_equal: os << q << "!=" << q; break; diff --git a/libbuild2/token.hxx b/libbuild2/token.hxx index 4cf1f51..e48c088 100644 --- a/libbuild2/token.hxx +++ b/libbuild2/token.hxx @@ -53,6 +53,7 @@ namespace build2 assign, // = prepend, // =+ append, // += + default_assign, // ?= equal, // == not_equal, // != -- cgit v1.1