aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/parser.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-09-26 13:36:44 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-09-30 15:30:35 +0200
commite59c2bc979293d8cdea3f9733ecd59c080fce63c (patch)
tree337fefcc20ee6b6de53514caceefc9d45e5bd7d8 /libbuild2/parser.cxx
parent333f468d264f0fa36a772b10b885fff6160ae4c7 (diff)
Add support for `case` pattern alternatives
case <pattern>[ | <pattern>...]
Diffstat (limited to 'libbuild2/parser.cxx')
-rw-r--r--libbuild2/parser.cxx46
1 files changed, 38 insertions, 8 deletions
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index 2a5c31d..33b6d11 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -2092,10 +2092,14 @@ namespace build2
// case <pattern>[, <pattern>...]
// ...
//
+ // case <pattern>[|<pattern>]
+ //
// default
// ...
// }
+ assert (!pre_parse_); // Used to skip pattern alternatives.
+
// Parse and evaluate the values we are matching. Similar to if-else, we
// expand patterns.
//
@@ -2186,7 +2190,13 @@ namespace build2
// Parse the patterns and match them against the values. Note that
// here we don't expand patterns in names.
//
- mode (lexer_mode::values); // Recognize `,`.
+ mode (lexer_mode::case_patterns); // Recognize `|` and `,`.
+
+ auto parse_pattern = [this] (token& t, type& tt)
+ {
+ return parse_value (
+ t, tt, pattern_mode::ignore, "pattern", nullptr);
+ };
for (size_t i (0);; ++i)
{
@@ -2194,16 +2204,36 @@ namespace build2
if (tt == type::newline || tt == type::eos)
fail (t) << "expected case pattern instead of " << t;
- const location l (get_location (t));
+ if (i == vs.size ())
+ fail (t) << "more patterns than switch expressions";
- value p (
- parse_value (
- t, tt, pattern_mode::ignore, "pattern", nullptr));
+ // Handle pattern alternatives (<pattern>|<pattern>).
+ //
+ for (;; next (t, tt))
+ {
+ const location l (get_location (t));
+ value p (parse_pattern (t, tt));
+ take = compare_values (type::equal, vs[i], p, l);
- if (i == vs.size ())
- fail (l) << "more patterns than switch expressions";
+ if (tt != type::bit_or)
+ break;
+
+ if (take)
+ {
+ // Use the pre-parse mechanism to skip remaining alternatives.
+ //
+ pre_parse_ = true;
+ do
+ {
+ next (t, tt); // Skip `|`.
+ parse_pattern (t, tt);
+ }
+ while (tt == type::bit_or);
+ pre_parse_ = false;
- take = compare_values (type::equal, vs[i], p, l);
+ break;
+ }
+ }
if (!take)
{