aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/build
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2022-10-20 19:39:57 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2022-10-21 11:50:52 +0300
commit4881a227779a78db1de2a7723e2a86f2b61453b3 (patch)
treec85ca613cc1a9dc4952d0cc7b0c55603f2b4edfa /libbuild2/build
parente5efed8e25180b9d009edf2a06e5151db107e883 (diff)
Change attribute syntax in script to come after variable in set and for (set x [...], for x [...])
Diffstat (limited to 'libbuild2/build')
-rw-r--r--libbuild2/build/script/parser+for.test.testscript20
-rw-r--r--libbuild2/build/script/parser.cxx62
2 files changed, 49 insertions, 33 deletions
diff --git a/libbuild2/build/script/parser+for.test.testscript b/libbuild2/build/script/parser+for.test.testscript
index 2a9f169..847b253 100644
--- a/libbuild2/build/script/parser+for.test.testscript
+++ b/libbuild2/build/script/parser+for.test.testscript
@@ -69,10 +69,10 @@
%cmd (b/|'b\\')%
EOO
- : typed-var-value
+ : typed-elem
:
$* <<EOI >>~%EOO%
- for [dir_path] x: a b
+ for x [dir_path]: a b
cmd $x
end
EOI
@@ -80,10 +80,10 @@
%cmd (b/|'b\\')%
EOO
- : typed-values-var-value
+ : typed-elem-value
:
$* <<EOI >>~%EOO%
- for [dir_path] x: [strings] a b
+ for x [dir_path]: [strings] a b
cmd $x
end
EOI
@@ -341,14 +341,14 @@
echo a b | for x
EOO
- : typed-var-value
+ : typed-elem
:
$* <<EOI >>EOO
- echo 'a b' | for -w [dir_paths] x
+ echo 'a b' | for -w x [dir_path]
cmd $x
end
EOI
- echo 'a b' | for -w [dir_paths] x
+ echo 'a b' | for -w x [dir_path]
EOO
}
@@ -579,14 +579,14 @@
for x b <a
EOO
- : typed-var-value
+ : typed-elem
:
$* <<EOI >>EOO
- for -w [dir_path] x <'a b'
+ for -w x [dir_path] <'a b'
cmd $x
end
EOI
- for -w [dir_path] x <'a b'
+ for -w x [dir_path] <'a b'
EOO
}
diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx
index 77fdfee..cb1fbef 100644
--- a/libbuild2/build/script/parser.cxx
+++ b/libbuild2/build/script/parser.cxx
@@ -213,8 +213,7 @@ namespace build2
// Determine the line type/start token.
//
- line_type lt (
- pre_parse_line_start (t, tt, lexer_mode::second_token));
+ line_type lt (pre_parse_line_start (t, tt, lexer_mode::second_token));
line ln;
@@ -258,17 +257,16 @@ namespace build2
// or the third (x <...) one. Note that the second form (... | for
// x) is handled separately.
//
- // @@ Do we diagnose `... | for x: ...`?
- //
- // If the next token doesn't introduce a variable (doesn't start
- // attributes and doesn't look like a variable name), then this is
- // the third form. Otherwise, if colon follows the variable name,
- // then this is the first form and the third form otherwise.
+ // If the next token doesn't look like a variable name, then this
+ // is the third form. Otherwise, if colon follows the variable
+ // name, potentially after the attributes, then this is the first
+ // form and the third form otherwise.
//
// Note that for the third form we will need to pass the 'for'
// token as a program name to the command expression parsing
// function since it will be gone from the token stream by that
- // time. Thus, we save it.
+ // time. Thus, we save it. We also need to make sure the sensing
+ // always leaves the variable name token in t/tt.
//
// Note also that in this model it won't be possible to support
// options in the first form.
@@ -277,7 +275,7 @@ namespace build2
assert (pt.type == type::word && pt.value == "for");
mode (lexer_mode::for_loop);
- next_with_attributes (t, tt);
+ next (t, tt);
// Note that we also consider special variable names (those that
// don't clash with the command line elements like redirects, etc)
@@ -285,30 +283,48 @@ namespace build2
//
string& n (t.value);
- if (tt == type::lsbrace || // Attributes.
- (tt == type::word && // Variable name.
- t.qtype == quote_type::unquoted &&
- (n[0] == '_' || alpha (n[0]) || n == "~")))
+ if (tt == type::word && t.qtype == quote_type::unquoted &&
+ (n[0] == '_' || alpha (n[0]) || // Variable.
+ n == "~")) // Special variable.
{
- attributes_push (t, tt);
-
- if (tt != type::word || t.qtype != quote_type::unquoted)
- fail (t) << "expected variable name instead of " << t;
+ // Detect patterns analogous to parse_variable_name() (so we
+ // diagnose `for x[string]: ...`).
+ //
+ if (n.find_first_of ("[*?") != string::npos)
+ fail (t) << "expected variable name instead of " << n;
if (special_variable (n))
fail (t) << "attempt to set '" << n << "' special variable";
+ // Parse out the element attributes, if present.
+ //
+ if (lexer_->peek_char ().first == '[')
+ {
+ // Save the variable name token before the attributes parsing
+ // and restore it afterwards. Also make sure that the token
+ // which follows the attributes stays in the stream.
+ //
+ token vt (move (t));
+ next_with_attributes (t, tt);
+
+ attributes_push (t, tt,
+ true /* standalone */,
+ false /* next_token */);
+
+ t = move (vt);
+ tt = t.type;
+ }
+
if (lexer_->peek_char ().first == ':')
lt = line_type::cmd_for_args;
}
if (lt == line_type::cmd_for_stream) // for x <...
{
- // At this point `t` contains the token that follows the `for`
- // token and, potentially, the attributes. Now pre-parse the
- // command expression in the command_line lexer mode starting
- // from this position and also passing the 'for' token as a
- // program name.
+ // At this point t/tt contains the variable name token. Now
+ // pre-parse the command expression in the command_line lexer
+ // mode starting from this position and also passing the 'for'
+ // token as a program name.
//
// Note that the fact that the potential attributes are already
// parsed doesn't affect the command expression pre-parsing.