aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-03-26 07:03:50 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-03-26 07:09:22 +0200
commitdfd19b9637c6b917a40413a57b391d7ff27f50da (patch)
tree9855eacfe9d3f7b2099d8019aec6ee93cbb977d7
parent0588e48ac1499388f4d2ad5bc03fe9f63782f161 (diff)
Make buildfile parser reset'able
Note that the testscript parser (which derives from the buildfile parser) is (still) not reset'able (this functionality is currently not needed so why complicate things).
-rw-r--r--libbuild2/parser.cxx44
-rw-r--r--libbuild2/parser.hxx32
2 files changed, 55 insertions, 21 deletions
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index fbf3bda..2cb51c6 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -212,6 +212,17 @@ namespace build2
};
void parser::
+ reset ()
+ {
+ pre_parse_ = false;
+ attributes_.clear ();
+ default_target_ = nullptr;
+ peeked_ = false;
+ replay_ = replay::stop;
+ replay_data_.clear ();
+ }
+
+ void parser::
parse_buildfile (istream& is, const path_name& in, scope& root, scope& base)
{
lexer l (is, in);
@@ -223,12 +234,13 @@ namespace build2
{
path_ = &l.name ();
lexer_ = &l;
+
root_ = &root;
scope_ = &base;
- pbase_ = scope_->src_path_;
target_ = nullptr;
prerequisite_ = nullptr;
- default_target_ = nullptr;
+
+ pbase_ = scope_->src_path_;
enter_buildfile (*path_); // Needs scope_.
@@ -249,11 +261,14 @@ namespace build2
{
path_ = &l.name ();
lexer_ = &l;
+
+ root_ = nullptr;
scope_ = &s;
- pbase_ = scope_->src_path_; // Normally NULL.
target_ = nullptr;
prerequisite_ = nullptr;
+ pbase_ = scope_->src_path_; // Normally NULL.
+
token t;
type tt;
parse_variable (t, tt, var, kind);
@@ -268,11 +283,14 @@ namespace build2
{
path_ = &l.name ();
lexer_ = &l;
+
+ root_ = nullptr;
scope_ = &s;
- pbase_ = b;
target_ = nullptr;
prerequisite_ = nullptr;
+ pbase_ = b;
+
token t;
type tt;
value rhs (parse_variable_value (t, tt));
@@ -1968,9 +1986,9 @@ namespace build2
if (val.type != nullptr)
untypify (val);
- export_value_ = move (val).as<names> ();
+ export_value = move (val).as<names> ();
- if (export_value_.empty ())
+ if (export_value.empty ())
fail (l) << "empty value in export";
next_after_newline (t, tt);
@@ -3675,7 +3693,7 @@ namespace build2
bool has (tt == type::lsbrace);
if (!pre_parse_)
- attributes_.push (attributes {has, l, {}});
+ attributes_.push_back (attributes {has, l, {}});
if (!has)
return make_pair (false, l);
@@ -3727,7 +3745,7 @@ namespace build2
}
if (!pre_parse_)
- attributes_.top ().ats.emplace_back (move (n), move (v));
+ attributes_.back ().ats.emplace_back (move (n), move (v));
if (tt == type::comma)
next (t, tt);
@@ -5592,18 +5610,20 @@ namespace build2
buildspec parser::
parse_buildspec (istream& is, const path_name& in)
{
- path_ = &in;
-
// We do "effective escaping" and only for ['"\$(] (basically what's
// necessary inside a double-quoted literal plus the single quote).
//
+ path_ = &in;
lexer l (is, *path_, 1 /* line */, "\'\"\\$(");
lexer_ = &l;
- scope_ = root_ = &ctx.global_scope.rw ();
- pbase_ = &work; // Use current working directory.
+
+ root_ = &ctx.global_scope.rw ();
+ scope_ = root_;
target_ = nullptr;
prerequisite_ = nullptr;
+ pbase_ = &work; // Use current working directory.
+
// Turn on the buildspec mode/pairs recognition with '@' as the pair
// separator (e.g., src_root/@out_root/exe{foo bar}).
//
diff --git a/libbuild2/parser.hxx b/libbuild2/parser.hxx
index ba707da..6d78ce1 100644
--- a/libbuild2/parser.hxx
+++ b/libbuild2/parser.hxx
@@ -4,8 +4,6 @@
#ifndef LIBBUILD2_PARSER_HXX
#define LIBBUILD2_PARSER_HXX
-#include <stack>
-
#include <libbuild2/types.hxx>
#include <libbuild2/forward.hxx>
#include <libbuild2/utility.hxx>
@@ -60,9 +58,22 @@ namespace build2
parse_export_stub (istream& is, const path_name& name, scope& r, scope& b)
{
parse_buildfile (is, name, r, b);
- return move (export_value_);
+ return move (export_value);
}
+ // The above functions may be called again on the same parser instance
+ // after a reset.
+ //
+ void
+ reset ();
+
+ // Ad hoc parsing results for some cases.
+ //
+ // Note that these are not touched by reset().
+ //
+ public:
+ names export_value;
+
// Recursive descent parser.
//
protected:
@@ -246,13 +257,13 @@ namespace build2
attributes_pop ()
{
assert (!pre_parse_);
- attributes r (move (attributes_.top ()));
- attributes_.pop ();
+ attributes r (move (attributes_.back ()));
+ attributes_.pop_back ();
return r;
}
attributes&
- attributes_top () {return attributes_.top ();}
+ attributes_top () {return attributes_.back ();}
// Source a stream optionnaly entering it as a buildfile and performing
// the default target processing.
@@ -703,6 +714,10 @@ namespace build2
protected:
const fail_mark fail;
+ // Parser state.
+ //
+ // NOTE: remember to update reset() if adding anything here.
+ //
protected:
context& ctx;
stage stage_;
@@ -719,10 +734,9 @@ namespace build2
const dir_path* pbase_ = nullptr; // Current pattern base directory.
- std::stack<attributes> attributes_;
+ small_vector<attributes, 2> attributes_;
- target* default_target_;
- names export_value_;
+ target* default_target_ = nullptr;
replay_token peek_;
bool peeked_ = false;