diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2020-06-05 09:02:05 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2020-06-05 09:04:29 +0200 |
commit | e4a9ccadf751b88f5508ce9f890484bae33d1aaf (patch) | |
tree | 7c3045ce2a7dc450f4271a6f8fc7e7cc32fa1019 /libbuild2/parser.cxx | |
parent | 9ec2bdd87659438b4aa021a10c4a4977ef77118e (diff) |
Add ability to split ad hoc C++ recipe into global and local fragments
Specifically, now we can write:
{{ c++ 1 --
#include <map>
--
recipe
apply (action, target&) const override
{
...
}
}}
Diffstat (limited to 'libbuild2/parser.cxx')
-rw-r--r-- | libbuild2/parser.cxx | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index 6fb20fe..4b958e8 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -1103,6 +1103,10 @@ namespace build2 optional<string> lang; location lloc; + + // Use value mode to minimize the number of special characters. + // + mode (lexer_mode::value, '@'); if (next (t, tt) == type::newline) ; else if (tt == type::word) @@ -1132,12 +1136,12 @@ namespace build2 // ar.reset (new adhoc_script_rule (loc, st.value.size ())); } - else if (*lang == "c++") + else if (icasecmp (*lang, "c++") == 0) { // C++ // - // Parse recipe version. + // Parse recipe version and optional fragment separator. // if (tt == type::newline || tt == type::eos) fail (t) << "expected c++ recipe version instead of " << t; @@ -1145,18 +1149,42 @@ namespace build2 location nloc (get_location (t)); names ns (parse_names (t, tt, pattern_mode::ignore)); - uint64_t v; + uint64_t ver; try { - v = convert<uint64_t> (move (ns)); + if (ns.empty ()) + throw invalid_argument ("empty"); + + if (ns[0].pair) + throw invalid_argument ("pair in value"); + + ver = convert<uint64_t> (move (ns[0])); + } + catch (const invalid_argument& e) + { + fail (nloc) << "invalid c++ recipe version: " << e << endf; + } + + optional<string> sep; + if (ns.size () != 1) + try + { + if (ns.size () != 2) + throw invalid_argument ("multiple names"); + + sep = convert<string> (move (ns[1])); + + if (sep->empty ()) + throw invalid_argument ("empty"); } catch (const invalid_argument& e) { - fail (nloc) << "invalid c++ recipe version value: " << e + fail (nloc) << "invalid c++ recipe fragment separator: " << e << endf; } - ar.reset (new adhoc_cxx_rule (loc, st.value.size (), v)); + ar.reset ( + new adhoc_cxx_rule (loc, st.value.size (), ver, move (sep))); } else fail (lloc) << "unknown recipe language '" << *lang << "'"; |