// file : build2/test/script/parser -*- C++ -*- // copyright : Copyright (c) 2014-2016 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef BUILD2_TEST_SCRIPT_PARSER #define BUILD2_TEST_SCRIPT_PARSER #include #include #include #include #include #include namespace build2 { namespace test { namespace script { class lexer; class runner; class parser: protected build2::parser { // Pre-parse. Issue diagnostics and throw failed in case of an error. // public: void pre_parse (script&); void pre_parse (istream&, script&); // Recursive descent parser. // // Usually (but not always) parse functions receive the token/type // from which it should start consuming and in return the token/type // should contain the first token that has not been consumed. // // Functions that are called parse_*() rather than pre_parse_*() are // used for both stages. // protected: bool pre_parse_demote_group_scope (unique_ptr&); token pre_parse_scope_body (); unique_ptr pre_parse_scope_block (token&, token_type&, const string&); bool pre_parse_line (token&, token_type&, optional&, lines* = nullptr, bool one = false); bool pre_parse_if_else (token&, token_type&, optional&, lines&); bool pre_parse_if_else_scope (token&, token_type&, optional&, lines&); bool pre_parse_if_else_command (token&, token_type&, optional&, lines&); void pre_parse_directive (token&, token_type&); void pre_parse_include_line (names, location); description pre_parse_leading_description (token&, token_type&); description parse_trailing_description (token&, token_type&); value parse_variable_line (token&, token_type&); command_expr parse_command_line (token&, token_type&); // Ordered sequence of here-document redirects that we can expect to // see after the command line. // struct here_doc { size_t expr; // Index in command_expr. size_t pipe; // Index in command_pipe. int fd; // Redirect fd (0 - in, 1 - out, 2 - err). string end; bool literal; // Literal (single-quote). string modifiers; }; using here_docs = vector; pair parse_command_expr (token&, token_type&); command_exit parse_command_exit (token&, token_type&); void parse_here_documents (token&, token_type&, pair&); string parse_here_document (token&, token_type&, const string&, const string&); // Execute. Issue diagnostics and throw failed in case of an error. // public: void execute (script& s, runner& r) {if (!s.empty ()) execute (s, s, r);} void execute (scope&, script&, runner&); protected: void exec_scope_body (); void exec_lines (lines::iterator, lines::iterator, size_t&, bool); // Customization hooks. // protected: virtual lookup lookup_variable (name&&, string&&, const location&) override; // Number of quoted tokens since last reset. Note that this includes // the peeked token, if any. // protected: size_t quoted () const; void reset_quoted (token& current); size_t replay_quoted_; // Insert id into the id map checking for duplicates. // protected: const string& insert_id (string, location); // Set lexer pointers for both the current and the base classes. // protected: void set_lexer (lexer* l); protected: using base_parser = build2::parser; script* script_; // Pre-parse state. // using id_map = std::unordered_map; using include_set = std::set; group* group_; id_map* id_map_; include_set* include_set_; // Testscripts already included in this // scope. Must be absolute and normalized. lexer* lexer_; string id_prefix_; // Auto-derived id prefix. // Parse state. // runner* runner_; scope* scope_; }; } } } #endif // BUILD2_TEST_SCRIPT_PARSER