Home | History | Annotate | Download | only in gn
      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 
     17 class Parser;
     18 typedef scoped_ptr<ParseNode> (Parser::*PrefixFunc)(Token token);
     19 typedef scoped_ptr<ParseNode> (Parser::*InfixFunc)(scoped_ptr<ParseNode> left,
     20                                                    Token token);
     21 
     22 struct 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.
     31 class 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   scoped_ptr<ParseNode> DotOperator(scoped_ptr<ParseNode> left, Token token);
     65 
     66   // Helper to parse a comma separated list, optionally allowing trailing
     67   // commas (allowed in [] lists, not in function calls).
     68   scoped_ptr<ListNode> ParseList(Token::Type stop_before,
     69                                  bool allow_trailing_comma);
     70 
     71   scoped_ptr<ParseNode> ParseFile();
     72   scoped_ptr<ParseNode> ParseStatement();
     73   scoped_ptr<BlockNode> ParseBlock();
     74   scoped_ptr<ParseNode> ParseCondition();
     75 
     76   bool IsAssignment(const ParseNode* node) const;
     77   bool IsStatementBreak(Token::Type token_type) const;
     78 
     79   bool LookAhead(Token::Type type);
     80   bool Match(Token::Type type);
     81   Token Consume(Token::Type type, const char* error_message);
     82   Token Consume(Token::Type* types,
     83                 size_t num_types,
     84                 const char* error_message);
     85   Token Consume();
     86 
     87   const Token& cur_token() const { return tokens_[cur_]; }
     88 
     89   bool done() const { return at_end() || has_error(); }
     90   bool at_end() const { return cur_ >= tokens_.size(); }
     91   bool has_error() const { return err_->has_error(); }
     92 
     93   const std::vector<Token>& tokens_;
     94 
     95   static ParserHelper expressions_[Token::NUM_TYPES];
     96 
     97   Err* err_;
     98 
     99   // Current index into the tokens.
    100   size_t cur_;
    101 
    102   FRIEND_TEST_ALL_PREFIXES(Parser, BinaryOp);
    103   FRIEND_TEST_ALL_PREFIXES(Parser, Block);
    104   FRIEND_TEST_ALL_PREFIXES(Parser, Condition);
    105   FRIEND_TEST_ALL_PREFIXES(Parser, Expression);
    106   FRIEND_TEST_ALL_PREFIXES(Parser, FunctionCall);
    107   FRIEND_TEST_ALL_PREFIXES(Parser, List);
    108   FRIEND_TEST_ALL_PREFIXES(Parser, ParenExpression);
    109   FRIEND_TEST_ALL_PREFIXES(Parser, UnaryOp);
    110 
    111   DISALLOW_COPY_AND_ASSIGN(Parser);
    112 };
    113 
    114 #endif  // TOOLS_GN_PARSER_H_
    115