From 9c45022422bc9826da36631bfe1184658956daaf Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 3 Dec 2015 17:49:12 +0200 Subject: 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 --- build/parser | 5 +++++ build/parser.cxx | 35 +++++++++++++++++++++++++++++++---- tests/directive/buildfile | 8 -------- tests/directive/test.out | 1 - tests/directive/test.sh | 3 --- tests/keyword/buildfile | 23 +++++++++++++++++++++++ tests/keyword/test.out | 2 ++ tests/keyword/test.sh | 3 +++ 8 files changed, 64 insertions(+), 16 deletions(-) delete mode 100644 tests/directive/buildfile delete mode 100644 tests/directive/test.out delete mode 100755 tests/directive/test.sh create mode 100644 tests/keyword/buildfile create mode 100644 tests/keyword/test.out create mode 100755 tests/keyword/test.sh 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/directive/test.sh b/tests/directive/test.sh deleted file mode 100755 index b898b3c..0000000 --- a/tests/directive/test.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -valgrind -q b -q | diff -u test.out - 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 + +# ( +# +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/keyword/test.sh b/tests/keyword/test.sh new file mode 100755 index 0000000..b898b3c --- /dev/null +++ b/tests/keyword/test.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +valgrind -q b -q | diff -u test.out - -- cgit v1.1