diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2016-03-19 09:49:58 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2016-03-28 16:03:34 +0200 |
commit | bfbf2c9d3b2c79e0effa294c69d98b13154c0178 (patch) | |
tree | a6079a75131b3bfa74d2514cec73064846292826 | |
parent | cf59a5fa548cfa72ab0b56334afea5c031faf27b (diff) |
Change pairs semantics from separated to unseparated
Before we use to recognize 'x @ y' as a pair. Now it has to be written
unseparated, as 'x@y'. See tests/pairs for details on the new semantics.
-rw-r--r-- | build2/parser.cxx | 43 | ||||
-rw-r--r-- | tests/pairs/buildfile | 40 | ||||
-rw-r--r-- | tests/pairs/test.out | 27 | ||||
-rwxr-xr-x | tests/pairs/test.sh | 3 |
4 files changed, 99 insertions, 14 deletions
diff --git a/build2/parser.cxx b/build2/parser.cxx index c7f75b3..e1d63aa 100644 --- a/build2/parser.cxx +++ b/build2/parser.cxx @@ -1368,7 +1368,7 @@ namespace build2 { // If pair is not 0, then it is an index + 1 of the first half of // the pair for which we are parsing the second halves, e.g., - // a={b c d{e f} {}}. + // a@{b c d{e f} {}}. // // Buffer that is used to collect the complete name in case of @@ -1380,8 +1380,8 @@ namespace build2 string concat; // Number of names in the last group. This is used to detect when - // we need to add an empty first pair element (e.g., {@y}) or when - // we have a for now unsupported multi-name LHS (e.g., {x y}@z). + // we need to add an empty first pair element (e.g., @y) or when + // we have a (for now unsupported) multi-name LHS (e.g., {x y}@z). // size_t count (0); @@ -1402,15 +1402,11 @@ namespace build2 } else if (!first) { - // If we are chunking, stop at the next separated token. Unless - // current or next token is a pair separator, since we want the - // "x @ y" pair to be parsed as a single chunk. + // If we are chunking, stop at the next separated token. // - bool p (t.type == type::pair_separator); // Current token. - next (t, tt); - if (chunk && t.separated && (tt != type::pair_separator && !p)) + if (chunk && t.separated) break; } @@ -1811,12 +1807,15 @@ namespace build2 if (pair != 0) fail (t) << "nested pair on the right hand side of a pair"; - if (count > 1) - fail (t) << "multiple names on the left hand side of a pair"; + // Catch '@@'. Maybe we can use for something later (e.g., escaping). + // + if (!ns.empty () && ns.back ().pair) + fail (t) << "double pair separator"; - if (count == 0) + if (t.separated || count == 0) { - // Empty LHS, (e.g., {@y}), create an empty name. + // Empty LHS, (e.g., @y), create an empty name. The second test + // will be in effect if we have something like v=@y. // ns.emplace_back (pp, (dp != nullptr ? *dp : dir_path ()), @@ -1824,9 +1823,25 @@ namespace build2 string ()); count = 1; } + else if (count > 1) + fail (t) << "multiple names on the left hand side of a pair"; ns.back ().pair = true; tt = peek (); + + // If the next token is separated, then we have an empty RHS. Note + // that the case where it is not a name/group (e.g., a newline/eos) + // is handled below, once we are out of the loop. + // + if (peeked ().separated) + { + ns.emplace_back (pp, + (dp != nullptr ? *dp : dir_path ()), + (tp != nullptr ? *tp : string ()), + string ()); + count = 0; + } + continue; } @@ -1853,7 +1868,7 @@ namespace build2 fail (t) << "expected name instead of " << t; } - // Handle the empty RHS in a pair, (e.g., {y@}). + // Handle the empty RHS in a pair, (e.g., y@). // if (!ns.empty () && ns.back ().pair) { diff --git a/tests/pairs/buildfile b/tests/pairs/buildfile new file mode 100644 index 0000000..3b55044 --- /dev/null +++ b/tests/pairs/buildfile @@ -0,0 +1,40 @@ +print foo@bar # foo@bar +print foo@{bar} # foo@bar +print {foo}@bar # foo@bar +print {foo@bar} # foo@bar +print {{foo}@{bar}} # foo@bar +print "{foo}@bar" # {foo}@bar + +print foo@ # foo@{} +print {foo}@ # foo@{} +print {foo}@{} # foo@{} +print {foo}@ {FOO}@ # foo@{} FOO@{} +v=foo@ +print $v # foo@{} + +print @bar # {}@bar +print @{bar} # {}@bar +print {}@{bar} # {}@bar +print @{BAR} @{bar} # {}@BAR {}@bar +v=@bar +print $v # {}@bar + +print @ # {}@{} +print @{} # {}@{} +print {}@ # {}@{} +print {}@{} # {}@{} +print {@} # {}@{} +v=@ +print $v # {}@{} + +print @ @ # {}@{} {}@{} +v=@ @ +print $v # {}@{} {}@{} + +print @{bar BAR} # {}@bar {}@BAR +print @{bar {BAR}} # {}@bar {}@BAR +print foo@{bar BAR} # foo@bar foo@BAR + +#print @@ # error: double pair separator + +./: diff --git a/tests/pairs/test.out b/tests/pairs/test.out new file mode 100644 index 0000000..6033c84 --- /dev/null +++ b/tests/pairs/test.out @@ -0,0 +1,27 @@ +foo@bar +foo@bar +foo@bar +foo@bar +foo@bar +{foo}@bar +foo@{} +foo@{} +foo@{} +foo@{} FOO@{} +foo@{} +{}@bar +{}@bar +{}@bar +{}@BAR {}@bar +{}@bar +{}@{} +{}@{} +{}@{} +{}@{} +{}@{} +{}@{} +{}@{} {}@{} +{}@{} {}@{} +{}@bar {}@BAR +{}@bar {}@BAR +foo@bar foo@BAR diff --git a/tests/pairs/test.sh b/tests/pairs/test.sh new file mode 100755 index 0000000..b898b3c --- /dev/null +++ b/tests/pairs/test.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +valgrind -q b -q | diff -u test.out - |