aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/parser.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/parser.hxx')
-rw-r--r--libbuild2/parser.hxx155
1 files changed, 88 insertions, 67 deletions
diff --git a/libbuild2/parser.hxx b/libbuild2/parser.hxx
index 02d4f74..3e1d0a0 100644
--- a/libbuild2/parser.hxx
+++ b/libbuild2/parser.hxx
@@ -69,14 +69,20 @@ namespace build2
scope* root,
scope& base,
target* = nullptr,
- prerequisite* = nullptr);
+ prerequisite* = nullptr,
+ bool enter_buildfile = true);
void
parse_buildfile (lexer&,
scope* root,
scope& base,
target* = nullptr,
- prerequisite* = nullptr);
+ prerequisite* = nullptr,
+ bool enter_buildfile = true);
+
+ names
+ parse_export_stub (istream& is, const path_name& name,
+ const scope& rs, scope& gs, scope& ts);
buildspec
parse_buildspec (istream&, const path_name&);
@@ -87,14 +93,6 @@ namespace build2
pair<value, token>
parse_variable_value (lexer&, scope&, const dir_path*, const variable&);
- names
- parse_export_stub (istream& is, const path_name& name,
- scope& rs, scope& bs)
- {
- parse_buildfile (is, name, &rs, bs);
- return move (export_value);
- }
-
// Parse an evaluation context (`(...)`).
//
value
@@ -136,8 +134,20 @@ namespace build2
// config directive result.
//
- vector<pair<lookup, string>> config_report; // Config value and format.
- bool config_report_new = false; // One of values is new.
+ struct config_report
+ {
+ struct value
+ {
+ lookup val; // Value.
+ string fmt; // Format.
+ string org; // Original variable if config.report.variable.
+ };
+
+ project_name module; // Reporting module name.
+ vector<value> values;
+ bool new_value; // One of values is new.
+ };
+ small_vector<config_report, 1> config_reports;
// Misc utilities.
//
@@ -180,24 +190,29 @@ namespace build2
const target_type* = nullptr,
const string& = {});
- // Ad hoc target names inside < ... >.
+ // Group target names inside < ... >.
//
- struct adhoc_names_loc
+ struct group_names_loc
{
+ bool expl = false; // True -- explicit group, fase -- ad hoc.
+ location group_loc; // Group/primary target location.
+ location member_loc; // Members location.
names ns;
- location loc;
};
- using adhoc_names = small_vector<adhoc_names_loc, 1>;
+ using group_names = small_vector<group_names_loc, 1>;
vector<reference_wrapper<target>>
- enter_adhoc_members (adhoc_names_loc&&, bool);
+ enter_explicit_members (group_names_loc&&, bool);
+
+ vector<reference_wrapper<target>>
+ enter_adhoc_members (group_names_loc&&, bool);
small_vector<pair<reference_wrapper<target>, // Target.
vector<reference_wrapper<target>>>, // Ad hoc members.
1>
enter_targets (names&&, const location&,
- adhoc_names&&,
+ group_names&&,
size_t,
const attributes&);
@@ -207,7 +222,7 @@ namespace build2
void
parse_dependency (token&, token_type&,
names&&, const location&,
- adhoc_names&&,
+ group_names&&,
names&&, const location&,
const attributes&);
@@ -257,7 +272,9 @@ namespace build2
parse_if_else (token&, token_type&,
bool,
const function<void (
- token&, token_type&, bool, const string&)>&);
+ token&, token_type&, bool, const string&)>&,
+ const function<void (
+ token&, token_type&, const string&)>&);
void
parse_switch (token&, token_type&);
@@ -266,7 +283,9 @@ namespace build2
parse_switch (token&, token_type&,
bool,
const function<void (
- token&, token_type&, bool, const string&)>&);
+ token&, token_type&, bool, const string&)>&,
+ const function<void (
+ token&, token_type&, const string&)>&);
void
parse_for (token&, token_type&);
@@ -304,18 +323,6 @@ namespace build2
value&& rhs,
token_type assign_kind);
- void
- apply_value (const variable*, // Optional.
- value& lhs,
- value&& rhs,
- token_type assign_kind,
- const location&,
- //
- // Attributes:
- //
- const value_type* = nullptr,
- bool null = false);
-
// Return the value pack (values can be NULL/typed). Note that for an
// empty eval context ('()' potentially with whitespaces in between) the
// result is an empty pack, not a pack of one empty.
@@ -356,15 +363,25 @@ namespace build2
// Push a new entry into the attributes_ stack. If the next token is `[`
// then parse the attribute sequence until ']' storing the result in the
- // new stack entry. Then get the next token and, if standalone is false,
- // verify it is not newline/eos (i.e., there is something after it).
- // Return the indication of whether we have seen any attributes (note
- // that the `[]` empty list does not count) and the location of `[`.
+ // new stack entry. Then, if next_token is true, get the next token and,
+ // if standalone is false, verify it is not newline/eos (i.e., there is
+ // something after it). If the next token is read and it is a word or a
+ // "word-producing" token (`$` for variable expansions/function calls, `(`
+ // for eval contexts, and `{` for name generation), then verify that it is
+ // separated to reduce the possibility of confusing it with a wildcard
+ // pattern. Consider:
+ //
+ // ./: [abc]-foo.txt
+ //
+ // Return the indication of whether we have seen any attributes (note that
+ // the `[]` empty list does not count) and the location of `[`.
//
// Note that during pre-parsing nothing is pushed into the stack.
//
pair<bool, location>
- attributes_push (token&, token_type&, bool standalone = false);
+ attributes_push (token&, token_type&,
+ bool standalone = false,
+ bool next_token = true);
attributes
attributes_pop ()
@@ -378,15 +395,21 @@ namespace build2
attributes&
attributes_top () {return attributes_.back ();}
- // Source a stream optionnaly performing the default target processing.
- // If the specified path name has a real path, then also enter it as a
- // buildfile.
+ // Source a buildfile as a stream optionally performing the default target
+ // processing. If the specified path name has a real path, then also enter
+ // it as a buildfile.
+ //
+ // If default_target is nullopt, then disable the default target semantics
+ // as when loading boostrap.build or root.build. If it is false, then
+ // continue with the existing default_target value. If it is true, then
+ // start with a new default_value and call process_default_target() at
+ // the end.
//
void
- source (istream&,
- const path_name&,
- const location&,
- bool default_target);
+ source_buildfile (istream&,
+ const path_name&,
+ const location&,
+ optional<bool> default_target);
// The what argument is used in diagnostics (e.g., "expected <what>
// instead of ...".
@@ -418,14 +441,7 @@ namespace build2
const string* separators = &name_separators)
{
names ns;
- parse_names (t, tt,
- ns,
- pmode,
- chunk,
- what,
- separators,
- 0,
- nullopt, nullptr, nullptr);
+ parse_names (t, tt, ns, pmode, chunk, what, separators);
return ns;
}
@@ -447,14 +463,7 @@ namespace build2
bool chunk = false)
{
names ns;
- auto r (parse_names (t, tt,
- ns,
- pmode,
- chunk,
- what,
- separators,
- 0,
- nullopt, nullptr, nullptr));
+ auto r (parse_names (t, tt, ns, pmode, chunk, what, separators));
value v (r.type); // Potentially typed NULL value.
@@ -617,12 +626,15 @@ namespace build2
switch_scope (const dir_path& out_base);
void
- process_default_target (token&);
+ process_default_target (token&, const buildfile*);
- // Enter buildfile as a target.
+ private:
+ // Enter buildfile or buildfile-file like file (e.g., a recipe file) as a
+ // target.
//
- void
- enter_buildfile (const path&);
+ template <typename T>
+ const T&
+ enter_buildfile (const path&, optional<dir_path> out = nullopt);
// Lexer.
//
@@ -708,15 +720,24 @@ namespace build2
replay_data_[replay_i_].mode == m);
}
+ // In the replay mode return the lexing mode of the token returned by the
+ // subsequent next() or peek() call.
+ //
lexer_mode
mode () const
{
if (replay_ != replay::play)
+ {
return lexer_->mode ();
+ }
else
{
- assert (replay_i_ != replay_data_.size ());
- return replay_data_[replay_i_].mode;
+ assert (!peeked_ || replay_i_ != 0);
+
+ size_t i (!peeked_ ? replay_i_ : replay_i_ - 1);
+ assert (i != replay_data_.size ());
+
+ return replay_data_[i].mode;
}
}