// 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 #include #include #include #include "base/gtest_prod_util.h" #include "base/macros.h" #include "tools/gn/err.h" #include "tools/gn/parse_tree.h" class Parser; typedef std::unique_ptr (Parser::*PrefixFunc)(const Token& token); typedef std::unique_ptr ( Parser::*InfixFunc)(std::unique_ptr left, const Token& token); extern const char kGrammar_Help[]; struct ParserHelper { PrefixFunc prefix; InfixFunc infix; int precedence; }; // 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 Parse(const std::vector& tokens, Err* err); // Alternative to parsing that assumes the input is an expression. static std::unique_ptr ParseExpression( const std::vector& tokens, Err* err); // Alternative to parsing that assumes the input is a literal value. static std::unique_ptr ParseValue(const std::vector& tokens, Err* err); private: // Vector must be valid for lifetime of call. Parser(const std::vector& tokens, Err* err); ~Parser(); std::unique_ptr ParseExpression(); // Parses an expression with the given precedence or higher. std::unique_ptr ParseExpression(int precedence); // |PrefixFunc|s used in parsing expressions. std::unique_ptr Block(const Token& token); std::unique_ptr Literal(const Token& token); std::unique_ptr Name(const Token& token); std::unique_ptr Group(const Token& token); std::unique_ptr Not(const Token& token); std::unique_ptr List(const Token& token); std::unique_ptr BlockComment(const Token& token); // |InfixFunc|s used in parsing expressions. std::unique_ptr BinaryOperator(std::unique_ptr left, const Token& token); std::unique_ptr IdentifierOrCall(std::unique_ptr left, const Token& token); std::unique_ptr Assignment(std::unique_ptr left, const Token& token); std::unique_ptr Subscript(std::unique_ptr left, const Token& token); std::unique_ptr DotOperator(std::unique_ptr 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 ParseList(const Token& start_token, Token::Type stop_before, bool allow_trailing_comma); std::unique_ptr ParseFile(); std::unique_ptr ParseStatement(); // Expects to be passed the token corresponding to the '{' and that the // current token is the one following the '{'. std::unique_ptr ParseBlock(const Token& begin_brace, BlockNode::ResultMode result_mode); std::unique_ptr ParseCondition(); // Generates a pre- and post-order traversal of the tree. void TraverseOrder(const ParseNode* root, std::vector* pre, std::vector* 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 tokens_; std::vector line_comment_tokens_; std::vector 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); }; #endif // TOOLS_GN_PARSER_H_