diff options
Diffstat (limited to 'libbuild2/parser.hxx')
-rw-r--r-- | libbuild2/parser.hxx | 155 |
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; } } |