blob: de1a08269b135149956d3e4e71ffc01f4aaa1936 [file] [log] [blame]
// 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);
};
using PrefixFunc = std::unique_ptr<ParseNode> (Parser::*)(const Token& token);
using InfixFunc = std::unique_ptr<ParseNode> (
Parser::*)(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_