1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef TOOLS_GN_PARSER_H_
6#define TOOLS_GN_PARSER_H_
7
8#include <map>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/gtest_prod_util.h"
13#include "base/memory/scoped_ptr.h"
14#include "tools/gn/err.h"
15#include "tools/gn/parse_tree.h"
16
17class Parser;
18typedef scoped_ptr<ParseNode> (Parser::*PrefixFunc)(Token token);
19typedef scoped_ptr<ParseNode> (Parser::*InfixFunc)(scoped_ptr<ParseNode> left,
20                                                   Token token);
21
22struct ParserHelper {
23  PrefixFunc prefix;
24  InfixFunc infix;
25  int precedence;
26};
27
28// Parses a series of tokens. The resulting AST will refer to the tokens passed
29// to the input, so the tokens an the file data they refer to must outlive your
30// use of the ParseNode.
31class Parser {
32 public:
33  // Will return a null pointer and set the err on error.
34  static scoped_ptr<ParseNode> Parse(const std::vector<Token>& tokens,
35                                     Err* err);
36
37  // Alternative to parsing that assumes the input is an expression.
38  static scoped_ptr<ParseNode> ParseExpression(const std::vector<Token>& tokens,
39                                               Err* err);
40
41  scoped_ptr<ParseNode> ParseExpression();
42
43 private:
44  // Vector must be valid for lifetime of call.
45  Parser(const std::vector<Token>& tokens, Err* err);
46  ~Parser();
47
48  // Parses an expression with the given precedence or higher.
49  scoped_ptr<ParseNode> ParseExpression(int precedence);
50
51  // |PrefixFunc|s used in parsing expressions.
52  scoped_ptr<ParseNode> Literal(Token token);
53  scoped_ptr<ParseNode> Name(Token token);
54  scoped_ptr<ParseNode> Group(Token token);
55  scoped_ptr<ParseNode> Not(Token token);
56  scoped_ptr<ParseNode> List(Token token);
57
58  // |InfixFunc|s used in parsing expressions.
59  scoped_ptr<ParseNode> BinaryOperator(scoped_ptr<ParseNode> left, Token token);
60  scoped_ptr<ParseNode> IdentifierOrCall(scoped_ptr<ParseNode> left,
61                                         Token token);
62  scoped_ptr<ParseNode> Assignment(scoped_ptr<ParseNode> left, Token token);
63  scoped_ptr<ParseNode> Subscript(scoped_ptr<ParseNode> left, Token token);
64
65  // Helper to parse a comma separated list, optionally allowing trailing
66  // commas (allowed in [] lists, not in function calls).
67  scoped_ptr<ListNode> ParseList(Token::Type stop_before,
68                                 bool allow_trailing_comma);
69
70  scoped_ptr<ParseNode> ParseFile();
71  scoped_ptr<ParseNode> ParseStatement();
72  scoped_ptr<BlockNode> ParseBlock();
73  scoped_ptr<ParseNode> ParseCondition();
74
75  bool IsAssignment(const ParseNode* node) const;
76  bool IsStatementBreak(Token::Type token_type) const;
77
78  bool LookAhead(Token::Type type);
79  bool Match(Token::Type type);
80  Token Consume(Token::Type type, const char* error_message);
81  Token Consume(Token::Type* types,
82                size_t num_types,
83                const char* error_message);
84  Token Consume();
85
86  const Token& cur_token() const { return tokens_[cur_]; }
87
88  bool done() const { return at_end() || has_error(); }
89  bool at_end() const { return cur_ >= tokens_.size(); }
90  bool has_error() const { return err_->has_error(); }
91
92  const std::vector<Token>& tokens_;
93
94  static ParserHelper expressions_[Token::NUM_TYPES];
95
96  Err* err_;
97
98  // Current index into the tokens.
99  size_t cur_;
100
101  FRIEND_TEST_ALL_PREFIXES(Parser, BinaryOp);
102  FRIEND_TEST_ALL_PREFIXES(Parser, Block);
103  FRIEND_TEST_ALL_PREFIXES(Parser, Condition);
104  FRIEND_TEST_ALL_PREFIXES(Parser, Expression);
105  FRIEND_TEST_ALL_PREFIXES(Parser, FunctionCall);
106  FRIEND_TEST_ALL_PREFIXES(Parser, List);
107  FRIEND_TEST_ALL_PREFIXES(Parser, ParenExpression);
108  FRIEND_TEST_ALL_PREFIXES(Parser, UnaryOp);
109
110  DISALLOW_COPY_AND_ASSIGN(Parser);
111};
112
113#endif  // TOOLS_GN_PARSER_H_
114