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 /build | |
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
Diffstat (limited to 'build')
-rw-r--r-- | build/parser | 5 | ||||
-rw-r--r-- | build/parser.cxx | 35 |
2 files changed, 36 insertions, 4 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. // |