From a63e1809afd9a837821d6e8376cb14a36e7fc26e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 4 Jan 2017 17:44:39 +0200 Subject: Treat any testscript line that starts with dot as directive Even though we currently only recognize the include directive, we reserve any line that begins with a dot for future. --- build2/test/script/lexer.cxx | 7 +-- build2/test/script/parser.cxx | 56 ++++++++++++--------- build2/test/script/token | 2 + build2/test/script/token.cxx | 2 + unit-tests/test/script/lexer/first-token.test | 5 ++ unit-tests/test/script/parser/buildfile | 6 +-- unit-tests/test/script/parser/directive.test | 70 +++++++++++++++++++++++++++ unit-tests/test/script/parser/include.test | 50 +------------------ 8 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 unit-tests/test/script/parser/directive.test diff --git a/build2/test/script/lexer.cxx b/build2/test/script/lexer.cxx index ce6ed5d..bcd5885 100644 --- a/build2/test/script/lexer.cxx +++ b/build2/test/script/lexer.cxx @@ -41,10 +41,10 @@ namespace build2 case lexer_mode::first_token: { // First token on the script line. Like command_line but - // recognizes leading '+-{}' as tokens as well as variable + // recognizes leading '.+-{}' as tokens as well as variable // assignments as separators. // - // Note that to recognize only leading '+-{}' we shouldn't add + // Note that to recognize only leading '.+-{}' we shouldn't add // them to the separator strings. // s1 = ":;=+!|&<> $(#\t\n"; @@ -431,12 +431,13 @@ namespace build2 } } - // Plus/minus and left/right curly braces. + // Dot, plus/minus, and left/right curly braces. // if (m == lexer_mode::first_token) { switch (c) { + case '.': return make_token (type::dot); case '+': return make_token (type::plus); case '-': return make_token (type::minus); case '{': return make_token (type::lcbrace); diff --git a/build2/test/script/parser.cxx b/build2/test/script/parser.cxx index 99e4a66..dd5c5c7 100644 --- a/build2/test/script/parser.cxx +++ b/build2/test/script/parser.cxx @@ -174,7 +174,7 @@ namespace build2 // for (;;) { - // Start lexing each line recognizing leading ':+-{}'. + // Start lexing each line recognizing leading '.+-{}'. // tt = peek (lexer_mode::first_token); @@ -304,6 +304,31 @@ namespace build2 switch (tt) { + case type::dot: + { + // Directive. + // + next (t, tt); // Skip dot. + next (t, tt); // Get the directive name. + + if (tt != type::word || t.qtype != quote_type::unquoted) + fail (t) << "expected directive name instead of " << t; + + // Make sure we are not inside a test (i.e., after semi). + // + if (ls != nullptr) + fail (ll) << "directive after ';'"; + + const string& n (t.value); + + if (n == "include") + pre_parse_directive (t, tt); + else + fail (t) << "unknown directive '" << n << "'"; + + assert (tt == type::newline); + return false; + } case type::plus: case type::minus: { @@ -331,23 +356,19 @@ namespace build2 } default: { - // Either directive, variable assignment, or test command. + // Either variable assignment or test command. // replay_save (); // Start saving tokens from the current one. next (t, tt); - // Decide whether this is a variable assignment, directive or a - // command. - // - // It is a directive if the first token is an unquoted directive - // name. + // Decide whether this is a variable assignment or a command. // // It is an assignment if the first token is an unquoted name and // the next token is an assign/append/prepend operator. Assignment // to a computed variable name must use the set builtin. // - // Note also that directives/special commands take precedence over - // variable assignments. + // Note also thatspecial commands take precedence over variable + // assignments. // lt = line_type::cmd; // Default. @@ -355,20 +376,7 @@ namespace build2 { const string& n (t.value); - if (n == ".include") - { - replay_stop (); // Stop replay and discard the data. - - // Make sure we are not inside a test (i.e., after semi). - // - if (ls != nullptr) - fail (ll) << "directive after ';'"; - - pre_parse_directive (t, tt); - assert (tt == type::newline); - return false; - } - else if (n == "if") lt = line_type::cmd_if; + if (n == "if") lt = line_type::cmd_if; else if (n == "if!") lt = line_type::cmd_ifn; else if (n == "elif") lt = line_type::cmd_elif; else if (n == "elif!") lt = line_type::cmd_elifn; @@ -941,7 +949,7 @@ namespace build2 if (tt != type::newline) fail (t) << t << " after directive"; - if (d == ".include") + if (d == "include") pre_parse_include_line (move (args), move (l)); else assert (false); // Unhandled directive. diff --git a/build2/test/script/token b/build2/test/script/token index 117ccaa..2950353 100644 --- a/build2/test/script/token +++ b/build2/test/script/token @@ -26,6 +26,8 @@ namespace build2 semi = base_type::value_next, // ; + dot, // . + plus, // + minus, // - diff --git a/build2/test/script/token.cxx b/build2/test/script/token.cxx index 5552994..9e1833c 100644 --- a/build2/test/script/token.cxx +++ b/build2/test/script/token.cxx @@ -25,6 +25,8 @@ namespace build2 { case token_type::semi: os << q << ';' << q; break; + case token_type::dot: os << q << '.' << q; break; + case token_type::plus: os << q << '+' << q; break; case token_type::minus: os << q << '-' << q; break; diff --git a/unit-tests/test/script/lexer/first-token.test b/unit-tests/test/script/lexer/first-token.test index d42e0b2..8a6d39b 100644 --- a/unit-tests/test/script/lexer/first-token.test +++ b/unit-tests/test/script/lexer/first-token.test @@ -2,6 +2,11 @@ # test.arguments = first-token +$* <"." >>EOO # dot +. + +EOO + $* <";" >>EOO # semi ; diff --git a/unit-tests/test/script/parser/buildfile b/unit-tests/test/script/parser/buildfile index db75a4f..41fe34d 100644 --- a/unit-tests/test/script/parser/buildfile +++ b/unit-tests/test/script/parser/buildfile @@ -15,8 +15,8 @@ test/{target script/{token lexer parser regex script}} \ scheduler exe{driver}: cxx{driver} ../../../../build2/cxx{$src} $libs \ -test{cleanup command-if command-re-parse description exit expansion \ - here-document here-string include pipe-expr pre-parse redirect \ - scope scope-if setup-teardown} +test{cleanup command-if command-re-parse description directive exit \ + expansion here-document here-string include pipe-expr pre-parse \ + redirect scope scope-if setup-teardown} include ../../../../build2/ diff --git a/unit-tests/test/script/parser/directive.test b/unit-tests/test/script/parser/directive.test new file mode 100644 index 0000000..07cb65c --- /dev/null +++ b/unit-tests/test/script/parser/directive.test @@ -0,0 +1,70 @@ +: not-directive +: +$* <>EOO +x = x +".include" foo.test +\.include foo.test +EOI +.include foo.test +.include foo.test +EOO + +: expected-name +: +$* <>EOE != 0 +.$ +EOI +testscript:1:2: error: expected directive name instead of '$' +EOE + +: unknown-name +: +$* <>EOE != 0 +.bogus +EOI +testscript:1:2: error: unknown directive 'bogus' +EOE + +: separated +: +touch foo.test; +$* <>>"foo-$(build.version).test"; +cmd +EOI +$* <>EOO +.include "foo-$(build.version).test" +EOI +cmd +EOO + +: after-semi +: +$* <>EOE != 0 +cmd; +.include foo.test +EOI +testscript:2:1: error: directive after ';' +EOE + +: semi-after +: +$* <>EOE != 0 +.include foo.test; +cmd +EOI +testscript:1:18: error: ';' after directive +EOE diff --git a/unit-tests/test/script/parser/include.test b/unit-tests/test/script/parser/include.test index 1639d37..7910919 100644 --- a/unit-tests/test/script/parser/include.test +++ b/unit-tests/test/script/parser/include.test @@ -1,22 +1,3 @@ -: not-directive -: -$* <>EOO -x = x -".include" foo.test -.include'' foo.test -EOI -.include foo.test -.include foo.test -EOO - -: not-separated -: -touch foo.test; -$* <>>"foo-$(build.version).test"; -cmd -EOI -$* <>EOO -.include "foo-$(build.version).test" -EOI -cmd -EOO - -: after-semi -: -$* <>EOE != 0 -cmd; -.include foo.test -EOI -testscript:2:1: error: directive after ';' -EOE - -: semi-after -: -$* <>EOE != 0 -.include foo.test; -cmd -EOI -testscript:1:18: error: ';' after directive -EOE - : invalid-path : $* <>EOE != 0 .include "" EOI -testscript:1:1: error: invalid testscript include path '' +testscript:1:2: error: invalid testscript include path '' EOE : unable-open -- cgit v1.1