diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-03-02 09:10:28 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-03-02 09:10:28 +0200 |
commit | fbd3c230d3861084b7316a6d5a8597cb00c9510b (patch) | |
tree | a5e1d1f5aeb77d74c66ac9874925d6e951cc0d3a | |
parent | bbd05eb0c32a9614f012a1d9b75cef736a1d4150 (diff) |
Implement value lexing mode
So that we can do foo=g++ without having to resort to quoting
-rw-r--r-- | build/lexer | 11 | ||||
-rw-r--r-- | build/lexer.cxx | 76 |
2 files changed, 67 insertions, 20 deletions
diff --git a/build/lexer b/build/lexer index 1944727..1723ae0 100644 --- a/build/lexer +++ b/build/lexer @@ -100,10 +100,17 @@ namespace build std::uint64_t l_ {1}; std::uint64_t c_ {1}; - bool eos_ {false}; - bool unget_ {false}; xchar buf_ {0, 0, 0}; + + bool eos_ {false}; + + // Context-dependent lexing mode. In the value mode we don't treat + // certain characters (e.g., +, =) as special so that we can use + // them in the variable values, e.g., 'foo = g++'. + // + enum class mode {normal, value}; + mode mode_ {mode::normal}; }; } diff --git a/build/lexer.cxx b/build/lexer.cxx index 2870620..6836322 100644 --- a/build/lexer.cxx +++ b/build/lexer.cxx @@ -25,12 +25,13 @@ namespace build // case '\n': { + // Restore the normal mode at the end of the line. + // + if (mode_ == mode::value) + mode_ = mode::normal; + return token (token_type::newline, ln, cn); } - case ':': - { - return token (token_type::colon, ln, cn); - } case '{': { return token (token_type::lcbrace, ln, cn); @@ -39,16 +40,34 @@ namespace build { return token (token_type::rcbrace, ln, cn); } - case '=': - { - return token (token_type::equal, ln, cn); - } - case '+': + } + + // The following characters are not treated as special in the + // value mode. + // + if (mode_ != mode::value) + { + // NOTE: remember to update name() if adding new punctuations. + // + switch (c) { - if (get () != '=') - fail (c) << "expected = after +"; + case ':': + { + return token (token_type::colon, ln, cn); + } + case '=': + { + mode_ = mode::value; + return token (token_type::equal, ln, cn); + } + case '+': + { + if (get () != '=') + fail (c) << "expected = after +"; - return token (token_type::plus_equal, ln, cn); + mode_ = mode::value; + return token (token_type::plus_equal, ln, cn); + } } } @@ -127,35 +146,56 @@ namespace build for (c = peek (); !is_eos (c); c = peek ()) { + bool done (false); + + // The following characters are not treated as special in the + // value mode. + // + if (mode_ != mode::value) + { + switch (c) + { + case ':': + case '=': + case '+': + { + done = true; + break; + } + } + + if (done) + break; + } + switch (c) { case ' ': case '\t': case '\n': case '#': - case ':': case '{': case '}': - case '=': - case '+': { + done = true; break; } case '\\': { get (); lexeme += escape (); - continue; + break; } default: { get (); lexeme += c; - continue; + break; } } - break; + if (done) + break; } return token (lexeme, ln, cn); |