1d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// found in the LICENSE file. 4d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 5d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/parser.h" 6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/logging.h" 8d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/functions.h" 9d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/operators.h" 10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/token.h" 11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// grammar: 133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// 143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// file := (statement)* 153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// statement := block | if | assignment 163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// block := '{' statement* '}' 173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// if := 'if' '(' expr ')' statement [ else ] 183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// else := 'else' (if | statement)* 193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// assignment := ident {'=' | '+=' | '-='} expr 203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)enum Precedence { 22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch PRECEDENCE_ASSIGNMENT = 1, // Lowest precedence. 233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PRECEDENCE_OR = 2, 243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PRECEDENCE_AND = 3, 253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PRECEDENCE_EQUALITY = 4, 263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PRECEDENCE_RELATION = 5, 273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PRECEDENCE_SUM = 6, 283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PRECEDENCE_PREFIX = 7, 293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PRECEDENCE_CALL = 8, 30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch PRECEDENCE_DOT = 9, // Highest precedence. 313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// The top-level for blocks/ifs is recursive descent, the expression parser is 34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// a Pratt parser. The basic idea there is to have the precedences (and 35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// associativities) encoded relative to each other and only parse up until you 36effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// hit something of that precedence. There's a dispatch table in expressions_ 37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// at the top of parser.cc that describes how each token dispatches if it's 38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// seen as either a prefix or infix operator, and if it's infix, what its 39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// precedence is. 403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// 413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Refs: 423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// - http://javascript.crockford.com/tdop/tdop.html 433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// - http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ 443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Indexed by Token::Type. 463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)ParserHelper Parser::expressions_[] = { 473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, NULL, -1}, // INVALID 483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {&Parser::Literal, NULL, -1}, // INTEGER 493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {&Parser::Literal, NULL, -1}, // STRING 503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {&Parser::Literal, NULL, -1}, // TRUE_TOKEN 513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {&Parser::Literal, NULL, -1}, // FALSE_TOKEN 523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::Assignment, PRECEDENCE_ASSIGNMENT}, // EQUAL 533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::BinaryOperator, PRECEDENCE_SUM}, // PLUS 543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::BinaryOperator, PRECEDENCE_SUM}, // MINUS 553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::Assignment, PRECEDENCE_ASSIGNMENT}, // PLUS_EQUALS 563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::Assignment, PRECEDENCE_ASSIGNMENT}, // MINUS_EQUALS 573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::BinaryOperator, PRECEDENCE_EQUALITY}, // EQUAL_EQUAL 583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::BinaryOperator, PRECEDENCE_EQUALITY}, // NOT_EQUAL 593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::BinaryOperator, PRECEDENCE_RELATION}, // LESS_EQUAL 603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::BinaryOperator, PRECEDENCE_RELATION}, // GREATER_EQUAL 613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::BinaryOperator, PRECEDENCE_RELATION}, // LESS_THAN 623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::BinaryOperator, PRECEDENCE_RELATION}, // GREATER_THAN 633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::BinaryOperator, PRECEDENCE_AND}, // BOOLEAN_AND 643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, &Parser::BinaryOperator, PRECEDENCE_OR}, // BOOLEAN_OR 653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {&Parser::Not, NULL, -1}, // BANG 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {NULL, &Parser::DotOperator, PRECEDENCE_DOT}, // DOT 673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {&Parser::Group, NULL, -1}, // LEFT_PAREN 683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, NULL, -1}, // RIGHT_PAREN 693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {&Parser::List, &Parser::Subscript, PRECEDENCE_CALL}, // LEFT_BRACKET 703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, NULL, -1}, // RIGHT_BRACKET 713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, NULL, -1}, // LEFT_BRACE 723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, NULL, -1}, // RIGHT_BRACE 733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, NULL, -1}, // IF 743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, NULL, -1}, // ELSE 753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {&Parser::Name, &Parser::IdentifierOrCall, PRECEDENCE_CALL}, // IDENTIFIER 763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {NULL, NULL, -1}, // COMMA 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci {NULL, NULL, -1}, // UNCLASSIFIED_COMMENT 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci {NULL, NULL, -1}, // LINE_COMMENT 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci {NULL, NULL, -1}, // SUFFIX_COMMENT 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci {&Parser::BlockComment, NULL, -1}, // BLOCK_COMMENT 813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 83d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochParser::Parser(const std::vector<Token>& tokens, Err* err) 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : err_(err), cur_(0) { 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (std::vector<Token>::const_iterator i(tokens.begin()); i != tokens.end(); 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++i) { 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci switch(i->type()) { 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case Token::LINE_COMMENT: 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci line_comment_tokens_.push_back(*i); 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case Token::SUFFIX_COMMENT: 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci suffix_comment_tokens_.push_back(*i); 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci default: 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Note that BLOCK_COMMENTs (top-level standalone comments) are passed 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // through the real parser. 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci tokens_.push_back(*i); 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 101d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 102d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 103d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochParser::~Parser() { 104d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 105d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 106d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static 107d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<ParseNode> Parser::Parse(const std::vector<Token>& tokens, 108d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Err* err) { 109d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Parser p(tokens, err); 1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return p.ParseFile().PassAs<ParseNode>(); 111d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 112d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 113d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static 114d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<ParseNode> Parser::ParseExpression(const std::vector<Token>& tokens, 115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Err* err) { 116d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Parser p(tokens, err); 117d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return p.ParseExpression().Pass(); 118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 119d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool Parser::IsAssignment(const ParseNode* node) const { 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return node && node->AsBinaryOp() && 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) (node->AsBinaryOp()->op().type() == Token::EQUAL || 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) node->AsBinaryOp()->op().type() == Token::PLUS_EQUALS || 1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) node->AsBinaryOp()->op().type() == Token::MINUS_EQUALS); 125d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 126d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool Parser::IsStatementBreak(Token::Type token_type) const { 1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) switch (token_type) { 1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Token::IDENTIFIER: 1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Token::LEFT_BRACE: 1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Token::RIGHT_BRACE: 1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Token::IF: 1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Token::ELSE: 1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) default: 1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 137d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 138d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 139d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool Parser::LookAhead(Token::Type type) { 1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (at_end()) 1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return cur_token().type() == type; 1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 145d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool Parser::Match(Token::Type type) { 1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!LookAhead(type)) 1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Consume(); 1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 152d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Token Parser::Consume(Token::Type type, const char* error_message) { 1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Token::Type types[1] = { type }; 1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return Consume(types, 1, error_message); 156d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 157d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Token Parser::Consume(Token::Type* types, 1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) size_t num_types, 1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const char* error_message) { 1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (has_error()) { 1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Don't overwrite current error, but make progress through tokens so that 1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // a loop that's expecting a particular token will still terminate. 1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) cur_++; 1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return Token(Location(), Token::INVALID, base::StringPiece()); 166d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 167d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) { 1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const char kEOFMsg[] = "I hit EOF instead."; 1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (tokens_.empty()) 1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = Err(Location(), error_message, kEOFMsg); 1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) else 1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = Err(tokens_[tokens_.size() - 1], error_message, kEOFMsg); 1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return Token(Location(), Token::INVALID, base::StringPiece()); 174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 175d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (size_t i = 0; i < num_types; ++i) { 1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (cur_token().type() == types[i]) 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return tokens_[cur_++]; 179d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = Err(cur_token(), error_message); 1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return Token(Location(), Token::INVALID, base::StringPiece()); 1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 183d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Token Parser::Consume() { 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return tokens_[cur_++]; 186d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 187d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 188d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<ParseNode> Parser::ParseExpression() { 1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return ParseExpression(0); 1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::ParseExpression(int precedence) { 193d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) 1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(); 195d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Token token = Consume(); 1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PrefixFunc prefix = expressions_[token.type()].prefix; 198d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (prefix == NULL) { 2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = Err(token, 2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string("Unexpected token '") + token.value().as_string() + 2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string("'")); 2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(); 2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ParseNode> left = (this->*prefix)(token); 20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (has_error()) 20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return left.Pass(); 2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) while (!at_end() && !IsStatementBreak(cur_token().type()) && 2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) precedence <= expressions_[cur_token().type()].precedence) { 2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) token = Consume(); 2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) InfixFunc infix = expressions_[token.type()].infix; 2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (infix == NULL) { 2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = Err(token, 2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string("Unexpected token '") + 2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) token.value().as_string() + std::string("'")); 218d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 219d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) left = (this->*infix)(left.Pass(), token); 221d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 223d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 224d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return left.Pass(); 226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::Literal(Token token) { 2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(new LiteralNode(token)).Pass(); 2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::Name(Token token) { 2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return IdentifierOrCall(scoped_ptr<ParseNode>(), token).Pass(); 2343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 235d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<ParseNode> Parser::BlockComment(Token token) { 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<BlockCommentNode> comment(new BlockCommentNode()); 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci comment->set_comment(token); 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return comment.PassAs<ParseNode>(); 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::Group(Token token) { 2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ParseNode> expr = ParseExpression(); 2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (has_error()) 2453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(); 2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Consume(Token::RIGHT_PAREN, "Expected ')'"); 2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return expr.Pass(); 2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 249d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::Not(Token token) { 2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1); 2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (has_error()) 2533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(); 2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<UnaryOpNode> unary_op(new UnaryOpNode); 2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) unary_op->set_op(token); 2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) unary_op->set_operand(expr.Pass()); 2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return unary_op.PassAs<ParseNode>(); 2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 259d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::List(Token node) { 2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<ParseNode> list(ParseList(node, Token::RIGHT_BRACKET, true)); 2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!has_error() && !at_end()) 2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Consume(Token::RIGHT_BRACKET, "Expected ']'"); 2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return list.Pass(); 2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 266d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::BinaryOperator(scoped_ptr<ParseNode> left, 2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Token token) { 2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ParseNode> right = 2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ParseExpression(expressions_[token.type()].precedence + 1); 2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!right) { 2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = 2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Err(token, 2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "Expected right hand side for '" + token.value().as_string() + "'"); 2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(); 276d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<BinaryOpNode> binary_op(new BinaryOpNode); 2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) binary_op->set_op(token); 2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) binary_op->set_left(left.Pass()); 2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) binary_op->set_right(right.Pass()); 2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return binary_op.PassAs<ParseNode>(); 2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 283d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::IdentifierOrCall(scoped_ptr<ParseNode> left, 2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Token token) { 2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ListNode> list(new ListNode); 2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) list->set_begin_token(token); 2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) list->set_end_token(token); 2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<BlockNode> block; 2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool has_arg = false; 2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (LookAhead(Token::LEFT_PAREN)) { 2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Token start_token = Consume(); 2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Parsing a function call. 2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) has_arg = true; 2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (Match(Token::RIGHT_PAREN)) { 2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Nothing, just an empty call. 2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci list = ParseList(start_token, Token::RIGHT_PAREN, false); 2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (has_error()) 3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(); 3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Consume(Token::RIGHT_PAREN, "Expected ')' after call"); 3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Optionally with a scope. 3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (LookAhead(Token::LEFT_BRACE)) { 3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) block = ParseBlock(); 3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (has_error()) 3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(); 3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 309d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 310d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!left && !has_arg) { 3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Not a function call, just a standalone identifier. 3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(new IdentifierNode(token)).Pass(); 314d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<FunctionCallNode> func_call(new FunctionCallNode); 3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) func_call->set_function(token); 3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) func_call->set_args(list.Pass()); 3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (block) 3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) func_call->set_block(block.Pass()); 3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return func_call.PassAs<ParseNode>(); 321d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 322d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::Assignment(scoped_ptr<ParseNode> left, 3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Token token) { 3253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (left->AsIdentifier() == NULL) { 3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = Err(left.get(), "Left-hand side of assignment must be identifier."); 3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(); 328d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ParseNode> value = ParseExpression(PRECEDENCE_ASSIGNMENT); 3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<BinaryOpNode> assign(new BinaryOpNode); 3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) assign->set_op(token); 3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) assign->set_left(left.Pass()); 3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) assign->set_right(value.Pass()); 3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return assign.PassAs<ParseNode>(); 3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 336d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::Subscript(scoped_ptr<ParseNode> left, 3383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Token token) { 3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO: Maybe support more complex expressions like a[0][0]. This would 3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // require work on the evaluator too. 3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (left->AsIdentifier() == NULL) { 342effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *err_ = Err(left.get(), "May only subscript identifiers.", 343effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "The thing on the left hand side of the [] must be an identifier\n" 344effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "and not an expression. If you need this, you'll have to assign the\n" 345effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "value to a temporary before subscripting. Sorry."); 3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(); 347d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ParseNode> value = ParseExpression(); 3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Consume(Token::RIGHT_BRACKET, "Expecting ']' after subscript."); 3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<AccessorNode> accessor(new AccessorNode); 3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) accessor->set_base(left->AsIdentifier()->value()); 3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) accessor->set_index(value.Pass()); 3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return accessor.PassAs<ParseNode>(); 354d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 355d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 356effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_ptr<ParseNode> Parser::DotOperator(scoped_ptr<ParseNode> left, 357effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Token token) { 358effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (left->AsIdentifier() == NULL) { 359effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *err_ = Err(left.get(), "May only use \".\" for identifiers.", 360effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "The thing on the left hand side of the dot must be an identifier\n" 361effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "and not an expression. If you need this, you'll have to assign the\n" 362effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "value to a temporary first. Sorry."); 363effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return scoped_ptr<ParseNode>(); 364effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 365effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 366effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<ParseNode> right = ParseExpression(PRECEDENCE_DOT); 367effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!right || !right->AsIdentifier()) { 368effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *err_ = Err(token, "Expected identifier for right-hand-side of \".\"", 369effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "Good: a.cookies\nBad: a.42\nLooks good but still bad: a.cookies()"); 370effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return scoped_ptr<ParseNode>(); 371effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 373effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<AccessorNode> accessor(new AccessorNode); 374effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch accessor->set_base(left->AsIdentifier()->value()); 375effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch accessor->set_member(scoped_ptr<IdentifierNode>( 376effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static_cast<IdentifierNode*>(right.release()))); 377effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return accessor.PassAs<ParseNode>(); 378effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 379effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Does not Consume the start or end token. 3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<ListNode> Parser::ParseList(Token start_token, 3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Token::Type stop_before, 3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool allow_trailing_comma) { 384d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<ListNode> list(new ListNode); 3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci list->set_begin_token(start_token); 3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool just_got_comma = false; 3875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bool first_time = true; 3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) while (!LookAhead(stop_before)) { 3895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!first_time) { 3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!just_got_comma) { 3915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Require commas separate things in lists. 3925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *err_ = Err(cur_token(), "Expected comma between items."); 3935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return scoped_ptr<ListNode>(); 3945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu first_time = false; 3975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Why _OR? We're parsing things that are higher precedence than the , 3993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // that separates the items of the list. , should appear lower than 4003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // boolean expressions (the lowest of which is OR), but above assignments. 4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) list->append_item(ParseExpression(PRECEDENCE_OR)); 402d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 403d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ListNode>(); 4043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (at_end()) { 4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = 4063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Err(tokens_[tokens_.size() - 1], "Unexpected end of file in list."); 4073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ListNode>(); 408d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (list->contents().back()->AsBlockComment()) { 4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If there was a comment inside the list, we don't need a comma to the 4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // next item, so pretend we got one, if we're expecting one. 4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci just_got_comma = allow_trailing_comma; 4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci just_got_comma = Match(Token::COMMA); 4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 4173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (just_got_comma && !allow_trailing_comma) { 4183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = Err(cur_token(), "Trailing comma"); 4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ListNode>(); 420d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 4213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) list->set_end_token(cur_token()); 422d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return list.Pass(); 423d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 424d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 4253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::ParseFile() { 4263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<BlockNode> file(new BlockNode(false)); 4273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (;;) { 4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (at_end()) 4293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) break; 4303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ParseNode> statement = ParseStatement(); 4313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!statement) 4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) break; 4333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) file->append_statement(statement.Pass()); 4343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 4353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!at_end() && !has_error()) 4363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = Err(cur_token(), "Unexpected here, should be newline."); 437d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 438d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(scottmg): If this is measurably expensive, it could be done only 4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // when necessary (when reformatting, or during tests). Comments are 4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // separate from the parse tree at this point, so downstream code can remain 4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // ignorant of them. 4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AssignComments(file.get()); 4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return file.PassAs<ParseNode>(); 4473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 448d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 4493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::ParseStatement() { 4503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (LookAhead(Token::LEFT_BRACE)) { 4513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return ParseBlock().PassAs<ParseNode>(); 4523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (LookAhead(Token::IF)) { 4533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return ParseCondition(); 4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (LookAhead(Token::BLOCK_COMMENT)) { 4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return BlockComment(Consume()); 4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 4573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(scottmg): Is this too strict? Just drop all the testing if we want 4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // to allow "pointless" expressions and return ParseExpression() directly. 4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ParseNode> stmt = ParseExpression(); 4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (stmt) { 4613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (stmt->AsFunctionCall() || IsAssignment(stmt.get())) 4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return stmt.Pass(); 4633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 4643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!has_error()) { 4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Token token = at_end() ? tokens_[tokens_.size() - 1] : cur_token(); 4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = Err(token, "Expecting assignment or function call."); 4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 468d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 469d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 470d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 471d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 4723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<BlockNode> Parser::ParseBlock() { 4733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Token begin_token = 4743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Consume(Token::LEFT_BRACE, "Expected '{' to start a block."); 4753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (has_error()) 4763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<BlockNode>(); 4773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<BlockNode> block(new BlockNode(true)); 4783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) block->set_begin_token(begin_token); 479d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 4803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (;;) { 4813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (LookAhead(Token::RIGHT_BRACE)) { 4823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) block->set_end_token(Consume()); 4833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) break; 4843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 485d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 4863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ParseNode> statement = ParseStatement(); 4873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!statement) 4883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<BlockNode>(); 4893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) block->append_statement(statement.Pass()); 490d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 4913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return block.Pass(); 492d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 493d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 4943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ParseNode> Parser::ParseCondition() { 4953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ConditionNode> condition(new ConditionNode); 4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci condition->set_if_token(Consume(Token::IF, "Expected 'if'")); 4973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Consume(Token::LEFT_PAREN, "Expected '(' after 'if'."); 4983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) condition->set_condition(ParseExpression()); 4993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (IsAssignment(condition->condition())) 5003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err_ = Err(condition->condition(), "Assignment not allowed in 'if'."); 5013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Consume(Token::RIGHT_PAREN, "Expected ')' after condition of 'if'."); 5023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) condition->set_if_true(ParseBlock().Pass()); 5033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (Match(Token::ELSE)) 5043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) condition->set_if_false(ParseStatement().Pass()); 5053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (has_error()) 5063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return scoped_ptr<ParseNode>(); 5073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return condition.PassAs<ParseNode>(); 508d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Parser::TraverseOrder(const ParseNode* root, 5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<const ParseNode*>* pre, 5121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<const ParseNode*>* post) { 5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (root) { 5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pre->push_back(root); 5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (const AccessorNode* accessor = root->AsAccessor()) { 5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(accessor->index(), pre, post); 5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(accessor->member(), pre, post); 5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (const BinaryOpNode* binop = root->AsBinaryOp()) { 5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(binop->left(), pre, post); 5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(binop->right(), pre, post); 5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (const BlockNode* block = root->AsBlock()) { 5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<ParseNode*>& statements = block->statements(); 5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (std::vector<ParseNode*>::const_iterator i(statements.begin()); 5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci i != statements.end(); 5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++i) { 5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(*i, pre, post); 5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (const ConditionNode* condition = root->AsConditionNode()) { 5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(condition->condition(), pre, post); 5311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(condition->if_true(), pre, post); 5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(condition->if_false(), pre, post); 5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) { 5341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(func_call->args(), pre, post); 5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(func_call->block(), pre, post); 5361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (root->AsIdentifier()) { 5371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Nothing. 5381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (const ListNode* list = root->AsList()) { 5391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<const ParseNode*>& contents = list->contents(); 5401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (std::vector<const ParseNode*>::const_iterator i(contents.begin()); 5411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci i != contents.end(); 5421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++i) { 5431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(*i, pre, post); 5441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (root->AsLiteral()) { 5461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Nothing. 5471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) { 5481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(unaryop->operand(), pre, post); 5491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (root->AsBlockComment()) { 5501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Nothing. 5511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 5521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(false) << "Unhandled case in TraverseOrder."; 5531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci post->push_back(root); 5561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Parser::AssignComments(ParseNode* file) { 5601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Start by generating a pre- and post- order traversal of the tree so we 5611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // can determine what's before and after comments. 5621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<const ParseNode*> pre; 5631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<const ParseNode*> post; 5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TraverseOrder(file, &pre, &post); 5651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Assign line comments to syntax immediately following. 5671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int cur_comment = 0; 5681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (std::vector<const ParseNode*>::const_iterator i = pre.begin(); 5691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci i != pre.end(); 5701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++i) { 5711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Location& start = (*i)->GetRange().begin(); 5721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci while (cur_comment < static_cast<int>(line_comment_tokens_.size())) { 5731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (start.byte() >= line_comment_tokens_[cur_comment].location().byte()) { 5741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const_cast<ParseNode*>(*i)->comments_mutable()->append_before( 5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci line_comment_tokens_[cur_comment]); 5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++cur_comment; 5771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Remaining line comments go at end of file. 5841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (; cur_comment < static_cast<int>(line_comment_tokens_.size()); 5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++cur_comment) 5861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file->comments_mutable()->append_after(line_comment_tokens_[cur_comment]); 5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Assign suffix to syntax immediately before. 5891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cur_comment = static_cast<int>(suffix_comment_tokens_.size() - 1); 5901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (std::vector<const ParseNode*>::const_reverse_iterator i = post.rbegin(); 5911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci i != post.rend(); 5921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++i) { 5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Don't assign suffix comments to the function call or list, but instead 5941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // to the last thing inside. 5951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if ((*i)->AsFunctionCall() || (*i)->AsList()) 5961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci continue; 5971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Location& start = (*i)->GetRange().begin(); 5991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Location& end = (*i)->GetRange().end(); 6001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Don't assign suffix comments to something that starts on an earlier 6021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // line, so that in: 6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // sources = [ "a", 6051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // "b" ] # comment 6061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 6071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // it's attached to "b", not sources = [ ... ]. 6081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (start.line_number() != end.line_number()) 6091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci continue; 6101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci while (cur_comment >= 0) { 6121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (end.byte() <= suffix_comment_tokens_[cur_comment].location().byte()) { 6131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const_cast<ParseNode*>(*i)->comments_mutable()->append_suffix( 6141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci suffix_comment_tokens_[cur_comment]); 6151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci --cur_comment; 6161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 6171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 6181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Suffix comments were assigned in reverse, so if there were multiple on 6221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the same node, they need to be reversed. 6231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); 6241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 626