From 70256514a09e4692c6839f5c2b21b7ec9c1055bd Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 30 Mar 2015 12:19:44 +0200 Subject: Add support for configurable pair separator, use @ instead of = in buildspec --- build/lexer | 14 ++++++++++---- build/lexer.cxx | 46 +++++++++++----------------------------------- build/parser.cxx | 36 +++++++++++++++++++----------------- build/token | 3 ++- 4 files changed, 42 insertions(+), 57 deletions(-) diff --git a/build/lexer b/build/lexer index 98a1390..5f91dc4 100644 --- a/build/lexer +++ b/build/lexer @@ -20,8 +20,8 @@ namespace build // them in the variable values, e.g., 'foo = g++'. In contrast, // in the variable mode, we restrict certain character (e.g., /) // from appearing in the name. The pairs mode is just like value - // except that we split names separated by '='. The pairs mode must - // be set manually. + // except that we split names separated by the pair character. + // The pairs mode must be set manually. // enum class lexer_mode {normal, value, variable, pairs}; @@ -30,10 +30,15 @@ namespace build public: lexer (std::istream& is, const std::string& name): is_ (is), fail (name) {} - // Note: sets mode for the next token. + // Note: sets mode for the next token. If mode is pairs, then + // the second argument specifies the separator character. // void - mode (lexer_mode m) {next_mode_ = m;} + mode (lexer_mode m, char pair_separator = '=') + { + next_mode_ = m; + pair_separator_ = pair_separator; + } lexer_mode mode () const {return mode_;} @@ -127,6 +132,7 @@ namespace build bool eos_ {false}; lexer_mode mode_ {lexer_mode::normal}; + char pair_separator_; lexer_mode next_mode_ {lexer_mode::normal}; // Switch to for next token. lexer_mode prev_mode_; // Return to after current mode expires. }; diff --git a/build/lexer.cxx b/build/lexer.cxx index 9683567..4cd9cda 100644 --- a/build/lexer.cxx +++ b/build/lexer.cxx @@ -64,6 +64,11 @@ namespace build } } + // Handle pair separator. + // + if (mode_ == lexer_mode::pairs && c == pair_separator_) + return token (token_type::pair_separator, sep, ln, cn); + // The following characters are not treated as special in the // value or pairs mode. // @@ -85,26 +90,9 @@ namespace build next_mode_ = lexer_mode::value; return token (token_type::plus_equal, sep, ln, cn); } - } - } - - // The following characters are not treated as special in the - // value mode. - // - if (mode_ != lexer_mode::value) - { - // NOTE: remember to update name() if adding new punctuations. - // - switch (c) - { case '=': { - // Unless we are already in the pairs mode, switch to the - // value mode. - // - if (next_mode_ != lexer_mode::pairs) - next_mode_ = lexer_mode::value; - + next_mode_ = lexer_mode::value; return token (token_type::equal, sep, ln, cn); } } @@ -126,6 +114,11 @@ namespace build { bool done (false); + // Handle pair separator. + // + if (mode_ == lexer_mode::pairs && c == pair_separator_) + break; + // The following characters are not treated as special in the // value or pairs mode. // @@ -135,23 +128,6 @@ namespace build { case ':': case '+': - { - done = true; - break; - } - } - - if (done) - break; - } - - // The following characters are not treated as special in the - // value mode. - // - if (mode_ != lexer_mode::value) - { - switch (c) - { case '=': { done = true; diff --git a/build/parser.cxx b/build/parser.cxx index b21dd6f..617f22b 100644 --- a/build/parser.cxx +++ b/build/parser.cxx @@ -976,7 +976,7 @@ namespace build // A pair separator (only in the pair mode). // - if (tt == type::equal && lexer_->mode () == lexer_mode::pairs) + if (tt == type::pair_separator) { if (pair != 0) fail (t) << "nested pair on the right hand side of a pair"; @@ -1043,9 +1043,10 @@ namespace build lexer_ = &l; scope_ = root_ = root_scope; - // Turn on pairs recognition (e.g., src_root/=out_root/exe{foo bar}). + // Turn on pairs recognition with '@' as the pair separator (e.g., + // src_root/@out_root/exe{foo bar}). // - lexer_->mode (lexer_mode::pairs); + lexer_->mode (lexer_mode::pairs, '@'); token t (type::eos, false, 0, 0); type tt; @@ -1084,9 +1085,9 @@ namespace build // We always start with one or more names. // if (tt != type::name && - tt != type::lcbrace && // Untyped name group: '{foo ...' - tt != type::dollar && // Variable expansion: '$foo ...' - tt != type::equal) // Empty pair LHS: '=foo ...' + tt != type::lcbrace && // Untyped name group: '{foo ...' + tt != type::dollar && // Variable expansion: '$foo ...' + tt != type::pair_separator) // Empty pair LHS: '=foo ...' fail (t) << "operation or target expected instead of " << t; location l (get_location (t, &path_)); // Start of names. @@ -1296,17 +1297,18 @@ namespace build { switch (t.type ()) { - case token_type::eos: os << ""; break; - case token_type::newline: os << ""; 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; + case token_type::eos: os << ""; break; + case token_type::newline: os << ""; break; + case token_type::pair_separator: os << ""; 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; diff --git a/build/token b/build/token index 670207d..f7e45dc 100644 --- a/build/token +++ b/build/token @@ -18,6 +18,7 @@ namespace build eos, name, newline, + pair_separator, colon, lcbrace, rcbrace, @@ -25,7 +26,7 @@ namespace build plus_equal, dollar, lparen, - rparen, + rparen }; class token -- cgit v1.1