aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/test/script/lexer.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/test/script/lexer.cxx')
-rw-r--r--libbuild2/test/script/lexer.cxx55
1 files changed, 33 insertions, 22 deletions
diff --git a/libbuild2/test/script/lexer.cxx b/libbuild2/test/script/lexer.cxx
index f9c8ac6..aec91fc 100644
--- a/libbuild2/test/script/lexer.cxx
+++ b/libbuild2/test/script/lexer.cxx
@@ -34,13 +34,16 @@ namespace build2
bool q (true); // quotes
if (!esc)
- {
- assert (!state_.empty ());
- esc = state_.top ().escapes;
- }
+ esc = current_state ().escapes;
switch (m)
{
+ case lexer_mode::for_loop:
+ {
+ // Leading tokens of the for-loop. Like command_line but also
+ // recognizes lsbrace like value.
+ }
+ // Fall through.
case lexer_mode::command_line:
{
s1 = ":;=!|&<> $(#\t\n";
@@ -107,7 +110,7 @@ namespace build2
}
assert (ps == '\0');
- state_.push (
+ mode_impl (
state {m, data, nullopt, false, false, ps, s, n, q, *esc, s1, s2});
}
@@ -116,12 +119,13 @@ namespace build2
{
token r;
- switch (state_.top ().mode)
+ switch (mode ())
{
case lexer_mode::command_line:
case lexer_mode::first_token:
case lexer_mode::second_token:
case lexer_mode::variable_line:
+ case lexer_mode::for_loop:
r = next_line ();
break;
case lexer_mode::description_line:
@@ -144,7 +148,7 @@ namespace build2
xchar c (get ());
uint64_t ln (c.line), cn (c.column);
- state st (state_.top ()); // Make copy (see first/second_token).
+ state st (current_state ()); // Make copy (see first/second_token).
lexer_mode m (st.mode);
auto make_token = [&sep, ln, cn] (type t)
@@ -157,9 +161,10 @@ namespace build2
//
if (st.lsbrace)
{
- assert (m == lexer_mode::variable_line);
+ assert (m == lexer_mode::variable_line ||
+ m == lexer_mode::for_loop);
- state_.top ().lsbrace = false; // Note: st is a copy.
+ current_state ().lsbrace = false; // Note: st is a copy.
if (c == '[' && (!st.lsbrace_unsep || !sep))
return make_token (type::lsbrace);
@@ -172,7 +177,7 @@ namespace build2
// we push any new mode (e.g., double quote).
//
if (m == lexer_mode::first_token || m == lexer_mode::second_token)
- state_.pop ();
+ expire_mode ();
// NOTE: remember to update mode() if adding new special characters.
@@ -183,7 +188,7 @@ namespace build2
// Expire variable value mode at the end of the line.
//
if (m == lexer_mode::variable_line)
- state_.pop ();
+ expire_mode ();
sep = true; // Treat newline as always separated.
return make_token (type::newline);
@@ -197,10 +202,11 @@ namespace build2
// Line separators.
//
- if (m == lexer_mode::command_line ||
- m == lexer_mode::first_token ||
- m == lexer_mode::second_token ||
- m == lexer_mode::variable_line)
+ if (m == lexer_mode::command_line ||
+ m == lexer_mode::first_token ||
+ m == lexer_mode::second_token ||
+ m == lexer_mode::variable_line ||
+ m == lexer_mode::for_loop)
{
switch (c)
{
@@ -210,7 +216,8 @@ namespace build2
if (m == lexer_mode::command_line ||
m == lexer_mode::first_token ||
- m == lexer_mode::second_token)
+ m == lexer_mode::second_token ||
+ m == lexer_mode::for_loop)
{
switch (c)
{
@@ -222,7 +229,8 @@ namespace build2
//
if (m == lexer_mode::command_line ||
m == lexer_mode::first_token ||
- m == lexer_mode::second_token)
+ m == lexer_mode::second_token ||
+ m == lexer_mode::for_loop)
{
switch (c)
{
@@ -244,7 +252,8 @@ namespace build2
//
if (m == lexer_mode::command_line ||
m == lexer_mode::first_token ||
- m == lexer_mode::second_token)
+ m == lexer_mode::second_token ||
+ m == lexer_mode::for_loop)
{
if (optional<token> t = next_cmd_op (c, sep))
return move (*t);
@@ -310,7 +319,7 @@ namespace build2
if (c == '\n')
{
get ();
- state_.pop (); // Expire the description mode.
+ expire_mode (); // Expire the description mode.
return token (type::newline, true, ln, cn, token_printer);
}
@@ -330,15 +339,17 @@ namespace build2
}
token lexer::
- word (state st, bool sep)
+ word (const state& st, bool sep)
{
- lexer_mode m (st.mode);
+ lexer_mode m (st.mode); // Save.
token r (base_lexer::word (st, sep));
if (m == lexer_mode::variable)
{
- if (r.value.size () == 1 && digit (r.value[0])) // $N
+ if (r.type == type::word &&
+ r.value.size () == 1 &&
+ digit (r.value[0])) // $N
{
xchar c (peek ());