| // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef TOOLS_GN_PARSER_H_ | |
| #define TOOLS_GN_PARSER_H_ | |
| #include <stddef.h> | |
| #include <map> | |
| #include <memory> | |
| #include <vector> | |
| #include "base/gtest_prod_util.h" | |
| #include "base/macros.h" | |
| #include "tools/gn/err.h" | |
| #include "tools/gn/parse_tree.h" | |
| extern const char kGrammar_Help[]; | |
| struct ParserHelper; | |
| // Parses a series of tokens. The resulting AST will refer to the tokens passed | |
| // to the input, so the tokens an the file data they refer to must outlive your | |
| // use of the ParseNode. | |
| class Parser { | |
| public: | |
| // Will return a null pointer and set the err on error. | |
| static std::unique_ptr<ParseNode> Parse(const std::vector<Token>& tokens, | |
| Err* err); | |
| // Alternative to parsing that assumes the input is an expression. | |
| static std::unique_ptr<ParseNode> ParseExpression( | |
| const std::vector<Token>& tokens, | |
| Err* err); | |
| // Alternative to parsing that assumes the input is a literal value. | |
| static std::unique_ptr<ParseNode> ParseValue(const std::vector<Token>& tokens, | |
| Err* err); | |
| private: | |
| // Vector must be valid for lifetime of call. | |
| Parser(const std::vector<Token>& tokens, Err* err); | |
| ~Parser(); | |
| std::unique_ptr<ParseNode> ParseExpression(); | |
| // Parses an expression with the given precedence or higher. | |
| std::unique_ptr<ParseNode> ParseExpression(int precedence); | |
| // |PrefixFunc|s used in parsing expressions. | |
| std::unique_ptr<ParseNode> Block(const Token& token); | |
| std::unique_ptr<ParseNode> Literal(const Token& token); | |
| std::unique_ptr<ParseNode> Name(const Token& token); | |
| std::unique_ptr<ParseNode> Group(const Token& token); | |
| std::unique_ptr<ParseNode> Not(const Token& token); | |
| std::unique_ptr<ParseNode> List(const Token& token); | |
| std::unique_ptr<ParseNode> BlockComment(const Token& token); | |
| // |InfixFunc|s used in parsing expressions. | |
| std::unique_ptr<ParseNode> BinaryOperator(std::unique_ptr<ParseNode> left, | |
| const Token& token); | |
| std::unique_ptr<ParseNode> IdentifierOrCall(std::unique_ptr<ParseNode> left, | |
| const Token& token); | |
| std::unique_ptr<ParseNode> Assignment(std::unique_ptr<ParseNode> left, | |
| const Token& token); | |
| std::unique_ptr<ParseNode> Subscript(std::unique_ptr<ParseNode> left, | |
| const Token& token); | |
| std::unique_ptr<ParseNode> DotOperator(std::unique_ptr<ParseNode> left, | |
| const Token& token); | |
| // Helper to parse a comma separated list, optionally allowing trailing | |
| // commas (allowed in [] lists, not in function calls). | |
| std::unique_ptr<ListNode> ParseList(const Token& start_token, | |
| Token::Type stop_before, | |
| bool allow_trailing_comma); | |
| std::unique_ptr<ParseNode> ParseFile(); | |
| std::unique_ptr<ParseNode> ParseStatement(); | |
| // Expects to be passed the token corresponding to the '{' and that the | |
| // current token is the one following the '{'. | |
| std::unique_ptr<BlockNode> ParseBlock(const Token& begin_brace, | |
| BlockNode::ResultMode result_mode); | |
| std::unique_ptr<ParseNode> ParseCondition(); | |
| // Generates a pre- and post-order traversal of the tree. | |
| void TraverseOrder(const ParseNode* root, | |
| std::vector<const ParseNode*>* pre, | |
| std::vector<const ParseNode*>* post); | |
| // Attach comments to nearby syntax. | |
| void AssignComments(ParseNode* file); | |
| bool IsAssignment(const ParseNode* node) const; | |
| bool IsStatementBreak(Token::Type token_type) const; | |
| bool LookAhead(Token::Type type); | |
| bool Match(Token::Type type); | |
| const Token& Consume(Token::Type type, const char* error_message); | |
| const Token& Consume(Token::Type* types, | |
| size_t num_types, | |
| const char* error_message); | |
| const Token& Consume(); | |
| // Call this only if !at_end(). | |
| const Token& cur_token() const { return tokens_[cur_]; } | |
| const Token& cur_or_last_token() const { | |
| return at_end() ? tokens_[tokens_.size() - 1] : cur_token(); | |
| } | |
| bool done() const { return at_end() || has_error(); } | |
| bool at_end() const { return cur_ >= tokens_.size(); } | |
| bool has_error() const { return err_->has_error(); } | |
| std::vector<Token> tokens_; | |
| std::vector<Token> line_comment_tokens_; | |
| std::vector<Token> suffix_comment_tokens_; | |
| static ParserHelper expressions_[Token::NUM_TYPES]; | |
| Token invalid_token_; | |
| Err* err_; | |
| // Current index into the tokens. | |
| size_t cur_; | |
| FRIEND_TEST_ALL_PREFIXES(Parser, BinaryOp); | |
| FRIEND_TEST_ALL_PREFIXES(Parser, Block); | |
| FRIEND_TEST_ALL_PREFIXES(Parser, Condition); | |
| FRIEND_TEST_ALL_PREFIXES(Parser, Expression); | |
| FRIEND_TEST_ALL_PREFIXES(Parser, FunctionCall); | |
| FRIEND_TEST_ALL_PREFIXES(Parser, List); | |
| FRIEND_TEST_ALL_PREFIXES(Parser, ParenExpression); | |
| FRIEND_TEST_ALL_PREFIXES(Parser, UnaryOp); | |
| DISALLOW_COPY_AND_ASSIGN(Parser); | |
| }; | |
| typedef std::unique_ptr<ParseNode> (Parser::*PrefixFunc)(const Token& token); | |
| typedef std::unique_ptr<ParseNode> ( | |
| Parser::*InfixFunc)(std::unique_ptr<ParseNode> left, const Token& token); | |
| struct ParserHelper { | |
| PrefixFunc prefix; | |
| InfixFunc infix; | |
| // Used only for infix operators. | |
| int precedence; | |
| }; | |
| // Renders parse subtree as a formatted text, indenting by the given number of | |
| // spaces. | |
| void RenderToText(const base::Value& node, int indent_level, | |
| std::ostringstream& os); | |
| #endif // TOOLS_GN_PARSER_H_ |