From 1b86963946082e10e879283fad51ba7ce4e942e2 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 10 Sep 2015 09:12:47 +0200 Subject: Add support for chunking name parsing --- build/parser | 19 ++++++++++++------- build/parser.cxx | 22 ++++++++++++++++++---- 2 files changed, 30 insertions(+), 11 deletions(-) (limited to 'build') diff --git a/build/parser b/build/parser index 0678a62..7787568 100644 --- a/build/parser +++ b/build/parser @@ -48,7 +48,7 @@ namespace build // Recursive descent parser. // - private: + protected: void clause (token&, token_type&); @@ -79,17 +79,22 @@ namespace build names_type eval (token&, token_type&); + // If chunk is true, then parse the smallest but complete, name-wise, + // chunk of input. Note that in this case you may still end up with + // multiple names, for example, {foo bar}. + // names_type - names (token& t, token_type& tt) + names (token& t, token_type& tt, bool chunk = false) { names_type ns; - names (t, tt, ns, 0, nullptr, nullptr, nullptr); + names (t, tt, ns, chunk, 0, nullptr, nullptr, nullptr); return ns; } void names (token&, token_type&, names_type&, + bool chunk, std::size_t pair, const std::string* prj, const dir_path* dir, @@ -102,7 +107,7 @@ namespace build // Utilities. // - private: + protected: // Switch to a new current scope. Note that this function might // also have to switch to a new root scope if the new current @@ -122,7 +127,7 @@ namespace build // Lexer. // - private: + protected: token_type next (token&, token_type&); @@ -138,10 +143,10 @@ namespace build // Diagnostics. // - private: + protected: const fail_mark fail; - private: + protected: const std::string* path_; // Path processed by diag_relative(). lexer* lexer_; target* target_; // Current target, if any. diff --git a/build/parser.cxx b/build/parser.cxx index 1ceb193..092ae3d 100644 --- a/build/parser.cxx +++ b/build/parser.cxx @@ -825,6 +825,7 @@ namespace build names (token& t, type& tt, names_type& ns, + bool chunk, size_t pair, const std::string* pp, const dir_path* dp, @@ -837,7 +838,7 @@ namespace build // Buffer that is used to collect the complete name in case of // an unseparated variable expansion or eval context, e.g., - // 'foo$bar$(baz)fox'. The idea is to concatenate all the + // 'foo$bar($baz)fox'. The idea is to concatenate all the // individual parts in this buffer and then re-inject it into // the loop as a single token. // @@ -865,7 +866,18 @@ namespace build concat.clear (); } else if (!first) + { + // If we are chunking, stop at the next separated token. Unless + // current or next token is a pair separator, since we want the + // "x = y" pair to be parsed as a single chunk. + // + if (chunk && + peeked ().separated && + (tt != type::pair_separator && t.type != type::pair_separator)) + break; + next (t, tt); + } // Name. // @@ -969,6 +981,7 @@ namespace build count = ns.size (); names (t, tt, ns, + false, (pair != 0 ? pair : (ns.empty () || ns.back ().pair == '\0' ? 0 : ns.size ())), @@ -1266,6 +1279,7 @@ namespace build count = ns.size (); names (t, tt, ns, + false, (pair != 0 ? pair : (ns.empty () || ns.back ().pair == '\0' ? 0 : ns.size ())), @@ -1279,7 +1293,7 @@ namespace build continue; } - // A pair separator (only in the pair mode). + // A pair separator (only in the pairs mode). // if (tt == type::pair_separator) { @@ -1308,8 +1322,6 @@ namespace build if (!first) break; - // Our caller expected this to be a name. - // if (tt == type::rcbrace) // Empty name, e.g., dir{}. { // If we are a second half of a pair, add another first half @@ -1325,6 +1337,8 @@ namespace build break; } else + // Our caller expected this to be a name. + // fail (t) << "expected name instead of " << t; } -- cgit v1.1