diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2016-10-24 18:00:05 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2016-11-04 09:26:35 +0200 |
commit | 79a83d6dd0f312a5e390f5627f68cc96c4427d33 (patch) | |
tree | f66a0a33ea9d18bf1e85d7c4503fc923028edc80 /build2/test | |
parent | 2c0a2b0d688b4450c72cde12ecedaa3fc3c9662a (diff) |
Add support for setup/teardown commands
Diffstat (limited to 'build2/test')
-rw-r--r-- | build2/test/script/lexer | 3 | ||||
-rw-r--r-- | build2/test/script/lexer.cxx | 57 | ||||
-rw-r--r-- | build2/test/script/parser | 2 | ||||
-rw-r--r-- | build2/test/script/parser.cxx | 64 | ||||
-rw-r--r-- | build2/test/script/script | 2 | ||||
-rw-r--r-- | build2/test/script/token | 3 | ||||
-rw-r--r-- | build2/test/script/token.cxx | 3 |
7 files changed, 105 insertions, 29 deletions
diff --git a/build2/test/script/lexer b/build2/test/script/lexer index 80e6036..53b88be 100644 --- a/build2/test/script/lexer +++ b/build2/test/script/lexer @@ -25,7 +25,8 @@ namespace build2 enum { script_line = base_type::value_next, - assign_line, // Auto-expires at the end of the token. + first_token, // Auto-expires at the end of the token. + second_token, // Auto-expires at the end of the token. variable_line, // Auto-expires at the end of the line. command_line, here_line diff --git a/build2/test/script/lexer.cxx b/build2/test/script/lexer.cxx index ea906a1..7ced2b9 100644 --- a/build2/test/script/lexer.cxx +++ b/build2/test/script/lexer.cxx @@ -30,14 +30,31 @@ namespace build2 s2 = " == "; break; } - case lexer_mode::assign_line: + case lexer_mode::first_token: { - // As script_line but with variable assignments. + // First token on the script line. Like script_line but recognizes + // leading plus/minus and variable assignments as separators. + // + // Note that to recognize only leading plus/minus we shouldn't add + // them to the separator strings. // s1 = ";=+!|&<> $(#\t\n"; s2 = " == "; break; } + case lexer_mode::second_token: + { + // Second token on the script line. Like script_line but + // recognizes leading variable assignments. + // + // Note that to recognize only leading assignments we shouldn't + // add them to the separator strings (so this is identical to + // script_line). + // + s1 = ";=!|&<> $(#\t\n"; + s2 = " == "; + break; + } case lexer_mode::variable_line: { // Like value except we recognize ';' and don't recognize '{'. @@ -87,7 +104,8 @@ namespace build2 switch (state_.top ().mode) { case lexer_mode::script_line: - case lexer_mode::assign_line: + case lexer_mode::first_token: + case lexer_mode::second_token: case lexer_mode::variable_line: case lexer_mode::command_line: case lexer_mode::here_line: r = next_line (); break; @@ -116,13 +134,13 @@ namespace build2 if (eos (c)) return make_token (type::eos); - state st (state_.top ()); // Make copy (see assign_line). + state st (state_.top ()); // Make copy (see first/second_token). lexer_mode m (st.mode); - // Expire the assign mode at the end of the token. Do it early in case + // Expire certain modes at the end of the token. Do it early in case // we push any new mode (e.g., double quote). // - if (m == lexer_mode::assign_line) + if (m == lexer_mode::first_token || m == lexer_mode::second_token) state_.pop (); // NOTE: remember to update mode() if adding new special characters. @@ -161,8 +179,9 @@ namespace build2 // Line separators. // - if (m == lexer_mode::script_line || - m == lexer_mode::assign_line || + if (m == lexer_mode::script_line || + m == lexer_mode::first_token || + m == lexer_mode::second_token || m == lexer_mode::variable_line) { switch (c) @@ -173,7 +192,9 @@ namespace build2 // Command line operator/separators. // - if (m == lexer_mode::script_line || m == lexer_mode::assign_line) + if (m == lexer_mode::script_line || + m == lexer_mode::first_token || + m == lexer_mode::second_token) { switch (c) { @@ -193,8 +214,9 @@ namespace build2 // Command operators/separators. // - if (m == lexer_mode::script_line || - m == lexer_mode::assign_line || + if (m == lexer_mode::script_line || + m == lexer_mode::first_token || + m == lexer_mode::second_token || m == lexer_mode::command_line) { switch (c) @@ -291,9 +313,20 @@ namespace build2 } } + // Plus/minus. + // + if (m == lexer_mode::first_token) + { + switch (c) + { + case '+': return make_token (type::plus); + case '-': return make_token (type::minus); + } + } + // Variable assignment (=, +=, =+). // - if (m == lexer_mode::assign_line) + if (m == lexer_mode::second_token) { switch (c) { diff --git a/build2/test/script/parser b/build2/test/script/parser index ef65c1a..2e8a9b1 100644 --- a/build2/test/script/parser +++ b/build2/test/script/parser @@ -64,7 +64,7 @@ namespace build2 parse_variable_line (token&, token_type&); bool - parse_test_line (token&, token_type&, size_t); + parse_command_line (token&, token_type&, size_t); command_exit parse_command_exit (token&, token_type&); diff --git a/build2/test/script/parser.cxx b/build2/test/script/parser.cxx index 2e5e9df..f8b414f 100644 --- a/build2/test/script/parser.cxx +++ b/build2/test/script/parser.cxx @@ -72,10 +72,9 @@ namespace build2 // replay_save (); - // We need to start lexing each line in the assign mode in order to - // recognize assignment operators as separators. + // Start lexing each line recognizing leading plus/minus. // - mode (lexer_mode::assign_line); + mode (lexer_mode::first_token); next (t, tt); if (group_->start_loc_.empty ()) @@ -111,11 +110,36 @@ namespace build2 // semicolon and we should add this one to the same place. // if (lines_ != nullptr) + { + switch (lt.first) + { + case line_type::setup: fail (ll) << "setup command in test"; + case line_type::tdown: fail (ll) << "teardown command in test"; + default: break; + } + ls = lines_; + } else { switch (lt.first) { + case line_type::setup: + { + if (!group_->scopes.empty ()) + fail (ll) << "setup command after tests"; + + if (!group_->tdown_.empty ()) + fail (ll) << "setup command after teardown"; + + ls = &group_->setup_; + break; + } + case line_type::tdown: + { + ls = &group_->tdown_; + break; + } case line_type::variable: { // If there is a semicolon after the variable then we assume @@ -142,10 +166,10 @@ namespace build2 // This will detect things like variable assignments between // tests. // - // @@ Can the teardown line be from a different file? - // if (!group_->tdown_.empty ()) { + // @@ Can the teardown line be from a different file? + // location tl ( get_location ( group_->tdown_.back ().tokens.front ().token)); @@ -249,11 +273,11 @@ namespace build2 // if (tt == type::word && !t.quoted) { - // Switch recognition of variable assignments for one more token. - // This is safe to do because we know we cannot be in the quoted - // mode (since the current token is not quoted). + // Switch recognition of leading variable assignments for the next + // token. This is safe to do because we know we cannot be in the + // quoted mode (since the current token is not quoted). // - mode (lexer_mode::assign_line); + mode (lexer_mode::second_token); type p (peek ()); if (p == type::assign || p == type::prepend || p == type::append) @@ -263,7 +287,14 @@ namespace build2 } } - return make_pair (line_type::test, parse_test_line (t, tt, 0)); + line_type lt (tt == type::plus ? line_type::setup : + tt == type::minus ? line_type::tdown : + line_type::test); + + if (lt != line_type::test) + next (t, tt); + + return make_pair (lt, parse_command_line (t, tt, 0)); } void parser:: @@ -272,7 +303,10 @@ namespace build2 switch (lt) { case line_type::variable: parse_variable_line (t, tt); break; - case line_type::test: parse_test_line (t, tt, li); break; + + case line_type::setup: + case line_type::tdown: next (t, tt); // Skip plus/minus fallthrough. + case line_type::test: parse_command_line (t, tt, li); break; } } @@ -363,7 +397,7 @@ namespace build2 } bool parser:: - parse_test_line (token& t, type& tt, size_t li) + parse_command_line (token& t, type& tt, size_t li) { command c; @@ -941,9 +975,11 @@ namespace build2 break; } - // Expand the line. + // Expand the line (can be blank). // - names ns (parse_names (t, tt, false, "here-document line", nullptr)); + names ns (tt != type::newline + ? parse_names (t, tt, false, "here-document line", nullptr) + : names ()); if (!pre_parse_) { diff --git a/build2/test/script/script b/build2/test/script/script index 8b6c3c0..2dbf7ce 100644 --- a/build2/test/script/script +++ b/build2/test/script/script @@ -26,7 +26,7 @@ namespace build2 // Pre-parse representation. // - enum class line_type {variable, test}; + enum class line_type {variable, setup, tdown, test}; struct line { diff --git a/build2/test/script/token b/build2/test/script/token index 1d4f2e4..f9352d2 100644 --- a/build2/test/script/token +++ b/build2/test/script/token @@ -26,6 +26,9 @@ namespace build2 semi = base_type::value_next, // ; + plus, // + + minus, // - + pipe, // | clean, // & log_and, // && diff --git a/build2/test/script/token.cxx b/build2/test/script/token.cxx index 2e86e29..549fe13 100644 --- a/build2/test/script/token.cxx +++ b/build2/test/script/token.cxx @@ -23,6 +23,9 @@ namespace build2 { case token_type::semi: os << q << ';' << q; break; + case token_type::plus: os << q << '+' << q; break; + case token_type::minus: os << q << '-' << q; break; + case token_type::pipe: os << q << '|' << q; break; case token_type::clean: os << q << '&' << q; break; case token_type::log_and: os << q << "&&" << q; break; |