From 62436ec452ea4453fdffc7cda2c7bfcdcbdd5a71 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 20 Oct 2016 15:06:48 +0200 Subject: Add support for ignoring separators inside names --- build2/parser | 25 +++++++++++++++++++------ build2/parser.cxx | 30 +++++++++++++++++++----------- 2 files changed, 38 insertions(+), 17 deletions(-) (limited to 'build2') diff --git a/build2/parser b/build2/parser index 59cdac2..4b84ae4 100644 --- a/build2/parser +++ b/build2/parser @@ -157,20 +157,28 @@ namespace build2 // 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} or $foo. + // multiple names, for example, {foo bar} or $foo. In the pre-parse mode + // always return empty list of names. // // The what argument is used in diagnostics (e.g., "expected // instead of ...". // - // In pre-parse mode always return empty list of names. + // The separators argument specifies the special characters to recognize + // inside the name. These can be the directory separators and the '%' + // project separator. Note that even if it is NULL, the result may still + // contain non-simple names due to variable expansions. // + static const string name_separators; + names parse_names (token& t, token_type& tt, bool chunk = false, - const char* what = "name") + const char* what = "name", + const string* separators = &name_separators) { names ns; - parse_names (t, tt, ns, chunk, what, 0, nullptr, nullptr, nullptr); + parse_names ( + t, tt, ns, chunk, what, separators, 0, nullptr, nullptr, nullptr); return ns; } @@ -180,10 +188,13 @@ namespace build2 // context evaluation. // value - parse_names_value (token& t, token_type& tt, const char* what = "name") + parse_names_value (token& t, token_type& tt, + const char* what = "name", + const string* separators = &name_separators) { names ns; - return parse_names (t, tt, ns, false, what, 0, nullptr, nullptr, nullptr) + return parse_names ( + t, tt, ns, false, what, separators, 0, nullptr, nullptr, nullptr) ? value (move (ns)) : value (nullptr); } @@ -195,6 +206,7 @@ namespace build2 names&, bool chunk = false, const char* what = "name", + const string* separators = &name_separators, size_t pair = 0, const string* prj = nullptr, const dir_path* dir = nullptr, @@ -204,6 +216,7 @@ namespace build2 parse_names_trailer (token&, token_type&, names&, const char* what, + const string* separators, size_t pair, const string* prj, const dir_path* dir, diff --git a/build2/parser.cxx b/build2/parser.cxx index dfe85be..64907b4 100644 --- a/build2/parser.cxx +++ b/build2/parser.cxx @@ -769,7 +769,7 @@ namespace build2 next (t, tt); const location l (get_location (t)); names ns (tt != type::newline && tt != type::eos - ? parse_names (t, tt) + ? parse_names (t, tt, false, "path", nullptr) : names ()); for (name& n: ns) @@ -845,7 +845,7 @@ namespace build2 next (t, tt); const location l (get_location (t)); names ns (tt != type::newline && tt != type::eos - ? parse_names (t, tt) + ? parse_names (t, tt, false, "path", nullptr) : names ()); for (name& n: ns) @@ -1176,7 +1176,7 @@ namespace build2 next (t, tt); const location l (get_location (t)); names ns (tt != type::newline && tt != type::eos - ? parse_names (t, tt) + ? parse_names (t, tt, false, "module", nullptr) : names ()); for (auto i (ns.begin ()); i != ns.end (); ++i) @@ -1315,7 +1315,7 @@ namespace build2 // Parse as names to get variable expansion, evaluation, etc. // const location nsl (get_location (t)); - names ns (parse_names (t, tt)); + names ns (parse_names (t, tt, false, "expression", nullptr)); // Should evaluate to 'true' or 'false'. // @@ -1841,7 +1841,7 @@ namespace build2 if (tt != type::rsbrace && tt != type::newline && tt != type::eos) { - names ns (parse_names (t, tt)); + names ns (parse_names (t, tt, false, "key-value", nullptr)); if (!pre_parse_) { @@ -1904,6 +1904,7 @@ namespace build2 parse_names_trailer (token& t, type& tt, names& ns, const char* what, + const string* separators, size_t pair, const string* pp, const dir_path* dp, @@ -1918,6 +1919,7 @@ namespace build2 ns, false, what, + separators, (pair != 0 ? pair : (ns.empty () || ns.back ().pair ? ns.size () : 0)), @@ -1935,7 +1937,8 @@ namespace build2 const location loc (get_location (t)); names x; // Parse into a separate list of names. - parse_names_trailer (t, tt, x, what, 0, nullptr, nullptr, nullptr); + parse_names_trailer ( + t, tt, x, what, separators, 0, nullptr, nullptr, nullptr); if (size_t n = x.size ()) { @@ -2015,7 +2018,7 @@ namespace build2 // Slashe(s) plus '%'. Note that here we assume '/' is there since that's // in our buildfile "syntax". // - static const string name_separators ( + const string parser::name_separators ( string (path::traits::directory_separators) + '%'); bool parser:: @@ -2023,6 +2026,7 @@ namespace build2 names& ns, bool chunk, const char* what, + const string* separators, size_t pair, const string* pp, const dir_path* dp, @@ -2116,9 +2120,11 @@ namespace build2 if (!pre_parse_) { - // Find slash or %. + // Find a separator (slash or %). // - string::size_type p (name.find_last_of (name_separators)); + string::size_type p (separators != nullptr + ? name.find_last_of (*separators) + : string::npos); // First take care of project. A project-qualified name is // not very common, so we can afford some copying for the @@ -2194,7 +2200,8 @@ namespace build2 tp1 = &t1; } - count = parse_names_trailer (t, tt, ns, what, pair, pp1, dp1, tp1); + count = parse_names_trailer ( + t, tt, ns, what, separators, pair, pp1, dp1, tp1); tt = peek (); continue; } @@ -2571,7 +2578,8 @@ namespace build2 // if (tt == type::lcbrace) { - count = parse_names_trailer (t, tt, ns, what, pair, pp, dp, tp); + count = parse_names_trailer ( + t, tt, ns, what, separators, pair, pp, dp, tp); tt = peek (); continue; } -- cgit v1.1