aboutsummaryrefslogtreecommitdiff
path: root/build2
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-10-20 15:33:39 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-11-04 09:26:33 +0200
commitea9d28c0e5fe16d5a0ade210f40cb98ea191d318 (patch)
treea7a3bc27a258d476d28220bcf0e6b7932f42d622 /build2
parentcf4af1e966c5f005d5cb4b4080a9e11c106982bd (diff)
Use special mode for attribute lexing
Diffstat (limited to 'build2')
-rw-r--r--build2/lexer14
-rw-r--r--build2/lexer.cxx34
-rw-r--r--build2/parser.cxx12
3 files changed, 37 insertions, 23 deletions
diff --git a/build2/lexer b/build2/lexer
index df8c852..f0a0fa6 100644
--- a/build2/lexer
+++ b/build2/lexer
@@ -21,15 +21,18 @@ namespace build2
// characters (e.g., '+', '=') as special so that we can use 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
- // eval mode is used in the evaluation context. Quoted are internal modes
- // and should not be set explicitly.
+ // attribute mode is like value except it doesn't treat '{' and '}' as
+ // special (so we cannot have name groups in attributes). The eval mode is
+ // used in the evaluation context. Quoted are internal modes and should not
+ // be set explicitly.
//
// Note that the normal, value, and eval modes split words separated by the
// pair character (to disable pairs one can pass '\0' as a pair character).
//
- // The alternnative modes must be set manually. The value mode is
- // automatically reset after the end of the line. The variable mode is reset
- // after the word token. And the eval mode is reset after the closing ')'.
+ // The alternnative modes must be set manually. The value mode automatically
+ // expires after the end of the line. The attribute mode expires after the
+ // closing ']'. The variable mode expires after the word token. And the eval
+ // mode expires after the closing ')'.
//
// Note that normally it is only safe to switch mode when the current token
// is not quoted (or, more generally, when you are not in the double-quoted
@@ -49,6 +52,7 @@ namespace build2
normal = base_type::value_next,
variable,
value,
+ attribute,
eval,
single_quoted,
double_quoted,
diff --git a/build2/lexer.cxx b/build2/lexer.cxx
index 8760c13..f2426e7 100644
--- a/build2/lexer.cxx
+++ b/build2/lexer.cxx
@@ -54,6 +54,13 @@ namespace build2
p = ps;
break;
}
+ case lexer_mode::attribute:
+ {
+ s1 = " $(]#\t\n";
+ s2 = " ";
+ p = ps;
+ break;
+ }
case lexer_mode::eval:
{
s1 = ":<>=! $(){}[]#\t\n";
@@ -87,11 +94,12 @@ namespace build2
switch (m)
{
case lexer_mode::normal:
- case lexer_mode::variable:
- case lexer_mode::value: break;
- case lexer_mode::eval: return next_eval ();
+ case lexer_mode::value:
+ case lexer_mode::attribute:
+ case lexer_mode::variable: break;
+ case lexer_mode::eval: return next_eval ();
case lexer_mode::double_quoted: return next_quoted ();
- default: assert (false); // Unhandled custom mode.
+ default: assert (false); // Unhandled custom mode.
}
bool sep (skip_spaces ());
@@ -109,8 +117,7 @@ namespace build2
// Handle pair separator.
//
- if ((m == lexer_mode::normal || m == lexer_mode::value) &&
- c == st.sep_pair)
+ if (c == st.sep_pair)
return make_token (type::pair_separator);
switch (c)
@@ -130,15 +137,24 @@ namespace build2
case '{': return make_token (type::lcbrace);
case '}': return make_token (type::rcbrace);
case '[': return make_token (type::lsbrace);
- case ']': return make_token (type::rsbrace);
+ case ']':
+ {
+ // Expire attribute mode after closing ']'.
+ //
+ if (m == lexer_mode::attribute)
+ state_.pop ();
+
+ return make_token (type::rsbrace);
+ }
case '$': return make_token (type::dollar);
case '(': return make_token (type::lparen);
case ')': return make_token (type::rparen);
}
- // The following characters are not treated as special in the value mode.
+ // The following characters are not treated as special in the value and
+ // attribute modes.
//
- if (m != lexer_mode::value)
+ if (m != lexer_mode::value && m != lexer_mode::attribute)
{
switch (c)
{
diff --git a/build2/parser.cxx b/build2/parser.cxx
index 64907b4..341ba34 100644
--- a/build2/parser.cxx
+++ b/build2/parser.cxx
@@ -1836,12 +1836,12 @@ namespace build2
// Using '@' for attribute key-value pairs would be just too ugly. Seeing
// that we control what goes into keys/values, let's use a much nicer '='.
//
- mode (lexer_mode::value, '=');
+ mode (lexer_mode::attribute, '=');
next (t, tt);
- if (tt != type::rsbrace && tt != type::newline && tt != type::eos)
+ if (tt != type::rsbrace)
{
- names ns (parse_names (t, tt, false, "key-value", nullptr));
+ names ns (parse_names (t, tt, false, "attribute", nullptr));
if (!pre_parse_)
{
@@ -1880,12 +1880,6 @@ namespace build2
}
}
- // Manually expire the value mode if we haven't reached newline/eos (where
- // it expires automatically).
- //
- if (mode () == lexer_mode::value)
- expire_mode ();
-
if (tt != type::rsbrace)
fail (t) << "expected ']' instead of " << t;