diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-12-03 17:49:12 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-12-03 17:49:12 +0200 |
commit | 9c45022422bc9826da36631bfe1184658956daaf (patch) | |
tree | f98bf7ef4ea82d34c4f05d7f452b840cfc77b0fe | |
parent | 6298f309bddaf3f279a724034e2d1d3ce58e0e1a (diff) |
Implement new potential directive keyword test
Now we can use directive names as variables and targets type, for
example:
print = foo # variable
print{foo}: # target
-rw-r--r-- | build/parser | 5 | ||||
-rw-r--r-- | build/parser.cxx | 35 | ||||
-rw-r--r-- | tests/directive/buildfile | 8 | ||||
-rw-r--r-- | tests/directive/test.out | 1 | ||||
-rw-r--r-- | tests/keyword/buildfile | 23 | ||||
-rw-r--r-- | tests/keyword/test.out | 2 | ||||
-rwxr-xr-x | tests/keyword/test.sh (renamed from tests/directive/test.sh) | 0 |
7 files changed, 61 insertions, 13 deletions
diff --git a/build/parser b/build/parser index ca27890..f3f88d5 100644 --- a/build/parser +++ b/build/parser @@ -128,6 +128,11 @@ namespace build void skip_block (token&, token_type&); + // Return true if the name token can be considered a directive keyword. + // + bool + keyword (token&); + // Buildspec. // buildspec diff --git a/build/parser.cxx b/build/parser.cxx index de4cfdc..a4e2af0 100644 --- a/build/parser.cxx +++ b/build/parser.cxx @@ -99,10 +99,9 @@ namespace build tt != type::colon) // Empty name: ': ...' break; // Something else. Let our caller handle that. - // See if this is one of the directives. This should be an - // unquoted literal name. + // See if this is one of the directives. // - if (tt == type::name && !t.quoted) + if (tt == type::name && keyword (t)) { const string& n (t.value); @@ -985,7 +984,7 @@ namespace build // See if we have another el* keyword. // - if (k != "else" && tt == type::name) + if (k != "else" && tt == type::name && keyword (t)) { const string& n (t.value); @@ -1739,6 +1738,34 @@ namespace build } } + bool parser:: + keyword (token& t) + { + assert (t.type == type::name); + + // The goal here is to allow using keywords as variable names and + // target types without imposing ugly restrictions/decorators on + // keywords (e.g., '.using' or 'USING'). A name is considered a + // potential keyword if: + // + // - it is not quoted [so a keyword can always be escaped] and + // - next token is separated or is '(' [so if(...) will work] and + // - next token is not '=' or '+=' [which means a "directive body" + // can never start with one of them]. + // + // See tests/keyword. + // + if (!t.quoted) + { + type pt (peek ()); + + return pt == type::lparen || + (pt != type::equal && pt != type::plus_equal && peeked ().separated); + } + + return false; + } + // Buildspec parsing. // diff --git a/tests/directive/buildfile b/tests/directive/buildfile deleted file mode 100644 index 0f83717..0000000 --- a/tests/directive/buildfile +++ /dev/null @@ -1,8 +0,0 @@ -"print" = a -'print' += b -pr"int" += c -print'' += d - -print $print - -./: diff --git a/tests/directive/test.out b/tests/directive/test.out deleted file mode 100644 index 8e13e46..0000000 --- a/tests/directive/test.out +++ /dev/null @@ -1 +0,0 @@ -a b c d diff --git a/tests/keyword/buildfile b/tests/keyword/buildfile new file mode 100644 index 0000000..cd91d33 --- /dev/null +++ b/tests/keyword/buildfile @@ -0,0 +1,23 @@ +# Quoting. +# +"print" = a +'print' += b +pr"int" += c +print'' += d + +# Not = or +=. +# +print += e + +print $print + +# <name>( +# +print(test) + +# Separated. +# +define print: file +print{foo}: + +./: diff --git a/tests/keyword/test.out b/tests/keyword/test.out new file mode 100644 index 0000000..729af10 --- /dev/null +++ b/tests/keyword/test.out @@ -0,0 +1,2 @@ +a b c d e +test diff --git a/tests/directive/test.sh b/tests/keyword/test.sh index b898b3c..b898b3c 100755 --- a/tests/directive/test.sh +++ b/tests/keyword/test.sh |