aboutsummaryrefslogtreecommitdiff
path: root/libbuild2
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-02-14 11:25:04 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-02-14 11:25:04 +0200
commit60c2c496357d3259c2fb29f7e2f1c3804eb5ad33 (patch)
treee9267dc523ce684ab177d56829e23c9b37b8b556 /libbuild2
parent14485a1ebe8daccf80498efbb0b88a6ab2021fa2 (diff)
Add parser::parse_eval() public API function
Diffstat (limited to 'libbuild2')
-rw-r--r--libbuild2/parser.cxx44
-rw-r--r--libbuild2/parser.hxx30
2 files changed, 62 insertions, 12 deletions
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index f42666b..9fbcd2b 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -355,6 +355,50 @@ namespace build2
return make_pair (move (lhs), move (t));
}
+ value parser::
+ parse_eval (lexer& l, scope& rs, scope& bs, pattern_mode pmode)
+ {
+ path_ = &l.name ();
+ lexer_ = &l;
+
+ root_ = &rs;
+ scope_ = &bs;
+ target_ = nullptr;
+ prerequisite_ = nullptr;
+
+ pbase_ = scope_->src_path_;
+
+ // Note that root_ may not be a project root.
+ //
+ auto_project_env penv (
+ stage_ != stage::boot && root_ != nullptr && root_->root_extra != nullptr
+ ? auto_project_env (*root_)
+ : auto_project_env ());
+
+ token t;
+ type tt;
+ next (t, tt);
+
+ if (tt != type::lparen)
+ fail (t) << "expected '(' instead of " << t;
+
+ location loc (get_location (t));
+ mode (lexer_mode::eval, '@');
+ next_with_attributes (t, tt);
+
+ values vs (parse_eval (t, tt, pmode));
+
+ if (next (t, tt) != type::eos)
+ fail (t) << "unexpected " << t;
+
+ switch (vs.size ())
+ {
+ case 0: return value (names ());
+ case 1: return move (vs[0]);
+ default: fail (loc) << "expected single value" << endf;
+ }
+ }
+
bool parser::
parse_clause (token& t, type& tt, bool one)
{
diff --git a/libbuild2/parser.hxx b/libbuild2/parser.hxx
index 0390e26..1474c5e 100644
--- a/libbuild2/parser.hxx
+++ b/libbuild2/parser.hxx
@@ -47,6 +47,16 @@ namespace build2
ctx (c),
stage_ (s) {}
+ // Pattern expansion mode.
+ //
+ enum class pattern_mode
+ {
+ ignore, // Treat as literals.
+ preserve, // Preserve as name pattern.
+ expand, // Expand to non-pattern names.
+ detect // Implementation detail mode (see code for more information).
+ };
+
// Issue diagnostics and throw failed in case of an error.
//
void
@@ -74,12 +84,18 @@ namespace build2
parse_variable_value (lexer&, scope&, const dir_path*, const variable&);
names
- parse_export_stub (istream& is, const path_name& name, scope& r, scope& b)
+ parse_export_stub (istream& is, const path_name& name,
+ scope& rs, scope& bs)
{
- parse_buildfile (is, name, &r, b);
+ parse_buildfile (is, name, &rs, bs);
return move (export_value);
}
+ // Parse an evaluation context (`(...)`).
+ //
+ value
+ parse_eval (lexer&, scope& rs, scope& bs, pattern_mode);
+
// The above functions may be called again on the same parser instance
// after a reset.
//
@@ -105,16 +121,6 @@ namespace build2
protected:
using pattern_type = name::pattern_type;
- // Pattern expansion mode.
- //
- enum class pattern_mode
- {
- ignore, // Treat as literals.
- preserve, // Preserve as name pattern.
- expand, // Expand to non-pattern names.
- detect // Implementation detail mode (see code for more information).
- };
-
// If one is true then parse a single (logical) line (logical means it
// can actually be several lines, e.g., an if-block). Return false if
// nothing has been parsed (i.e., we are still on the same token).