aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/parser.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-06-05 09:02:05 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-06-05 09:04:29 +0200
commite4a9ccadf751b88f5508ce9f890484bae33d1aaf (patch)
tree7c3045ce2a7dc450f4271a6f8fc7e7cc32fa1019 /libbuild2/parser.cxx
parent9ec2bdd87659438b4aa021a10c4a4977ef77118e (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.cxx40
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 << "'";