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 12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace { 13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 14d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Returns true if the two tokens are on the same line. We assume they're in 15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// the same file. 16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool IsSameLine(const Token& a, const Token& b) { 17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(a.location().file() == b.location().file()); 18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return a.location().line_number() == b.location().line_number(); 19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} // namespace 22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 23d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochParser::Parser(const std::vector<Token>& tokens, Err* err) 24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch : tokens_(tokens), 25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch err_(err), 26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_(0) { 27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 29d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochParser::~Parser() { 30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static 33d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<ParseNode> Parser::Parse(const std::vector<Token>& tokens, 34d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Err* err) { 35d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Parser p(tokens, err); 36d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return p.ParseBlock(false).PassAs<ParseNode>(); 37d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 38d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 39d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static 40d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<ParseNode> Parser::ParseExpression(const std::vector<Token>& tokens, 41d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Err* err) { 42d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Parser p(tokens, err); 43d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return p.ParseExpression().Pass(); 44d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 45d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 46d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool Parser::IsToken(Token::Type type, char* str) const { 47d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) 48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return false; 49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return cur_token().type() == type || cur_token().value() == str; 50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<AccessorNode> Parser::ParseAccessor() { 53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<AccessorNode> accessor(new AccessorNode); 54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(cur_token().type() == Token::IDENTIFIER); 56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch accessor->set_base(cur_token()); 57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; // Skip identifier. 58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; // Skip "[" (we know this exists because the existance of this 59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // token is how the caller knows it's an accessor. 60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) { 62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = MakeEOFError("Got EOF when looking for list index."); 63d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<AccessorNode>(); 64d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 65d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 66d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Get the expression. 67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<ParseNode> expr = ParseExpression().Pass(); 68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 69d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<AccessorNode>(); 70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) { 71d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = MakeEOFError("Got EOF when looking for list accessor ]"); 72d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<AccessorNode>(); 73d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch accessor->set_index(expr.Pass()); 75d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Skip over "]" 77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!cur_token().IsScoperEqualTo("]")) { 78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(cur_token(), "Expecting ]", 79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "You started a list access but didn't terminate it, and instead " 80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "I fould this\nstupid thing."); 81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<AccessorNode>(); 82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 83d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; 84d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return accessor.Pass(); 86d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 87d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 88d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Blocks at the file scope don't need {} so we have the option to ignore 89d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// them. When need_braces is set, we'll expect a begin an end brace. 90d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// 91d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// block := "{" block_contents "}" 92d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// block_contents := (expression | conditional | block)* 93d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<BlockNode> Parser::ParseBlock(bool need_braces) { 94d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<BlockNode> block(new BlockNode(true)); 95d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 96d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Eat initial { if necessary. 97d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token* opening_curly_brace; 98d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (need_braces) { 99d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) { 100d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = MakeEOFError("Got EOF when looking for { for block.", 101d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "It should have been after here."); 102d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<BlockNode>(); 103d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else if(!IsScopeBeginScoper(cur_token())) { 104d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(cur_token(), "Expecting { instead of this thing.", 105d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "THOU SHALT USE CURLY BRACES FOR ALL BLOCKS."); 106d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<BlockNode>(); 107d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 108d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch opening_curly_brace = &cur_token(); 109d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch block->set_begin_token(opening_curly_brace); 110d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; 111d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 112d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 113d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Loop until EOF or end brace found. 114d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch while (!at_end() && !IsScopeEndScoper(cur_token())) { 115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (cur_token().IsIdentifierEqualTo("if")) { 116d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Conditional. 117d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch block->append_statement(ParseCondition().PassAs<ParseNode>()); 118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else if (IsScopeBeginScoper(cur_token())) { 119d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Nested block. 120d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch block->append_statement(ParseBlock(true).PassAs<ParseNode>()); 121d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 122d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Everything else is an expression. 123d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch block->append_statement(ParseExpression().PassAs<ParseNode>()); 124d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 125d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 126d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<BlockNode>(); 127d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 128d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 129d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Eat the ending "}" if necessary. 130d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (need_braces) { 131d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end() || !IsScopeEndScoper(cur_token())) { 132d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(*opening_curly_brace, "Expecting }", 133d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "I ran headlong into the end of the file looking for the " 134d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "closing brace\ncorresponding to this one."); 135d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<BlockNode>(); 136d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 137d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch block->set_end_token(&cur_token()); 138d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; // Skip past "}". 139d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 141d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return block.Pass(); 142d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 143d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 144d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// conditional := "if (" expression ")" block [else_conditional] 145d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// else_conditional := ("else" block) | ("else" conditional) 146d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<ConditionNode> Parser::ParseCondition() { 147d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<ConditionNode> cond(new ConditionNode); 148d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 149d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Skip past "if". 150d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& if_token = cur_token(); 151d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cond->set_if_token(if_token); 152d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(if_token.IsIdentifierEqualTo("if")); 153d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; 154d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 155d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end() || !IsFunctionCallArgBeginScoper(cur_token())) { 156d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(if_token, "Expecting \"(\" after \"if\"", 157d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "Did you think this was Python or something?"); 158d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ConditionNode>(); 159d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 160d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 161d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Skip over (. 162d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& open_paren_token = cur_token(); 163d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; 164d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) { 165d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(if_token, "Unexpected EOF inside if condition"); 166d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ConditionNode>(); 167d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 168d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 169d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Condition inside (). 170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cond->set_condition(ParseExpression().Pass()); 171d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ConditionNode>(); 173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end() || !IsFunctionCallArgEndScoper(cur_token())) { 175d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(open_paren_token, "Expecting \")\" for \"if\" condition", 176d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "You didn't finish the thought you started here."); 177d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ConditionNode>(); 178d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 179d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; // Skip over ) 180d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 181d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Contents of {}. 182d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cond->set_if_true(ParseBlock(true).Pass()); 183d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 184d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ConditionNode>(); 185d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 186d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Optional "else" at the end. 187d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!at_end() && cur_token().IsIdentifierEqualTo("else")) { 188d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; 189d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 190d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The else may be followed by an if or a block. 191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) { 192d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = MakeEOFError("Ran into end of file after \"else\".", 193d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "else, WHAT?!?!?"); 194d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ConditionNode>(); 195d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 196d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (cur_token().IsIdentifierEqualTo("if")) { 197d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // "else if() {" 198d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cond->set_if_false(ParseCondition().PassAs<ParseNode>()); 199d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else if (IsScopeBeginScoper(cur_token())) { 200d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // "else {" 201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cond->set_if_false(ParseBlock(true).PassAs<ParseNode>()); 202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 203d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // else <anything else> 204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(cur_token(), "Expected \"if\" or \"{\" after \"else\".", 205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "This is neither of those things."); 206d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ConditionNode>(); 207d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 208d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 211d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ConditionNode>(); 212d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return cond.Pass(); 213d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 214d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 215d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// expression := paren_expression | accessor | identifier | literal | 216d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// funccall | unary_expression | binary_expression 217d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// 218d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// accessor := identifier <non-newline-whitespace>* "[" expression "]" 219d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// 220d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// The "non-newline-whitespace is used to differentiate between this case: 221d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// a[1] 222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// and this one: 223d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// a 224d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// [1] 225d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// The second one is kind of stupid (since it does nothing with the values) 226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// but is still legal. 227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<ParseNode> Parser::ParseExpression() { 228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<ParseNode> expr = ParseExpressionExceptBinaryOperators(); 229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // That may have hit EOF, in which case we can't have any binary operators. 233d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) 234d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return expr.Pass(); 235d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 236d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // TODO(brettw) handle operator precidence! 237d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Gobble up all subsequent expressions as long as there are binary 238d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // operators. 239d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 240d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (IsBinaryOperator(cur_token())) { 241d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<BinaryOpNode> binary_op(new BinaryOpNode); 242d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch binary_op->set_left(expr.Pass()); 243d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& operator_token = cur_token(); 244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch binary_op->set_op(operator_token); 245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; 246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) { 247d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(operator_token, "Unexpected EOF in expression.", 248d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "I was looking for the right-hand-side of this operator."); 249d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 250d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 251d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch binary_op->set_right(ParseExpression().Pass()); 252d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 253d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 254d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return binary_op.PassAs<ParseNode>(); 255d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 256d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 257d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return expr.Pass(); 258d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 259d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 260d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 261d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// This internal one does not handle binary operators, since it requires 262d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// looking at the "next" thing. The regular ParseExpression above handles it. 263d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<ParseNode> Parser::ParseExpressionExceptBinaryOperators() { 264d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) 265d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 266d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 267d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& token = cur_token(); 268d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 269d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Unary expression. 270d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (IsUnaryOperator(token)) 271d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ParseUnaryOp().PassAs<ParseNode>(); 272d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 273d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Parenthesized expressions. 274d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (token.IsScoperEqualTo("(")) 275d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ParseParenExpression(); 276d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 277d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Function calls. 278d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (token.type() == Token::IDENTIFIER) { 279d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_next_token() && IsFunctionCallArgBeginScoper(next_token())) 280d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ParseFunctionCall().PassAs<ParseNode>(); 281d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 282d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 283d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Lists. 284d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (token.IsScoperEqualTo("[")) { 285d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ParseList(Token(Location(), Token::SCOPER, "["), 286d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Token(Location(), Token::SCOPER, "]")).PassAs<ParseNode>(); 287d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 288d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 289d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Literals. 290d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (token.type() == Token::STRING || token.type() == Token::INTEGER) { 291d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; 292d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(new LiteralNode(token)); 293d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 294d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 295d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Accessors. 296d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (token.type() == Token::IDENTIFIER && 297d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch has_next_token() && next_token().IsScoperEqualTo("[") && 298d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch IsSameLine(token, next_token())) { 299d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ParseAccessor().PassAs<ParseNode>(); 300d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 301d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 302d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Identifiers. 303d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (token.type() == Token::IDENTIFIER) { 304d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; 305d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(new IdentifierNode(token)); 306d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 307d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 308d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Handle errors. 309d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (token.type() == Token::SEPARATOR) { 310d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(token, "Unexpected comma.", 311d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "You can't put a comma here, it must be in list separating " 312d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "complete\nthoughts."); 313d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else if (IsScopeBeginScoper(token)) { 314d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(token, "Unexpected token.", 315d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "You can't put a \"{\" scope here, it must be in a block."); 316d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 317d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(token, "Unexpected token.", 318d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "I was really hoping for something else here and you let me down."); 319d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 320d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 321d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 322d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 323d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// function_call := identifier "(" list_contents ")" 324d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// [<non-newline-whitespace>* block] 325d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<FunctionCallNode> Parser::ParseFunctionCall() { 326d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<FunctionCallNode> func(new FunctionCallNode); 327d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 328d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& function_token = cur_token(); 329d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch func->set_function(function_token); 330d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 331d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // This function should only get called when we know we have a function, 332d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // which only happens when there is a paren following the name. Skip past it. 333d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(has_next_token()); 334d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; // Skip past function name to (. 335d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& open_paren_token = cur_token(); 336d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(IsFunctionCallArgBeginScoper(open_paren_token)); 337d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 338d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) { 339d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(open_paren_token, "Unexpected EOF for function call.", 340d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "You didn't finish the thought you started here."); 341d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<FunctionCallNode>(); 342d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 343d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 344d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Arguments. 345d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch func->set_args(ParseList(Token(Location(), Token::SCOPER, "("), 346d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Token(Location(), Token::SCOPER, ")"))); 347d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 348d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<FunctionCallNode>(); 349d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 350d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Optional {} after function call for certain functions. The "{" must be on 351d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // the same line as the ")" to disambiguate the case of a function followed 352d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // by a random block just used for scoping purposes. 353d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!at_end() && IsScopeBeginScoper(cur_token())) { 354d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& args_end_token = tokens_[cur_ - 1]; 355d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(args_end_token.IsScoperEqualTo(")")); 356d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (IsSameLine(args_end_token, cur_token())) 357d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch func->set_block(ParseBlock(true).Pass()); 358d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 359d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 360d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 361d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<FunctionCallNode>(); 362d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return func.Pass(); 363d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 364d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 365d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// list := "[" expression* "]" 366d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// list_contents := [(expression ",")* expression [","]] 367d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// 368d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// The list_contents is also used in function calls surrounded by parens, so 369d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// this function takes the tokens that are expected to surround the list. 370d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<ListNode> Parser::ParseList(const Token& expected_begin, 371d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& expected_end) { 372d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<ListNode> list(new ListNode); 373d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 374d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& open_bracket_token = cur_token(); 375d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch list->set_begin_token(open_bracket_token); 376d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; // Skip "[" or "(". 377d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 378d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch bool need_separator = false; 379d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch while(true) { 380d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) { 381d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(open_bracket_token, "EOF found when parsing list.", 382d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "I expected a \"" + expected_end.value().as_string() + 383d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "\" corresponding to this one."); 384d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ListNode>(); 385d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 386d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (cur_token().type() == expected_end.type() && 387d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_token().value() == expected_end.value()) { 388d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch list->set_end_token(cur_token()); 389d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; 390d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 391d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 392d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 393d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (need_separator) { 394d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(!list->contents().empty()); 395d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch LocationRange prev_item_range = 396d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch list->contents().at(list->contents().size() - 1)->GetRange(); 397d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(prev_item_range.end(), 398d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "Need comma separating items in list.", 399d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "You probably need a comma after this thingy."); 400d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch err_->AppendRange(prev_item_range); 401d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ListNode>(); 402d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 403d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<ParseNode> expr = ParseExpression().Pass(); 404d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 405d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ListNode>(); 406d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch list->append_item(expr.Pass()); 407d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 408d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch need_separator = true; 409d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!at_end()) { 410d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Skip over the separator, marking that we found it. 411d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (cur_token().type() == Token::SEPARATOR) { 412d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; 413d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch need_separator = false; 414d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 415d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 416d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 417d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return list.Pass(); 418d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 419d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 420d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// paren_expression := "(" expression ")" 421d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<ParseNode> Parser::ParseParenExpression() { 422d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& open_paren_token = cur_token(); 423d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; // Skip over ( 424d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 425d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<ParseNode> ret = ParseExpression(); 426d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 427d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 428d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 429d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) { 430d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(open_paren_token, "EOF found when parsing expression.", 431d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "I was looking for a \")\" corresponding to this one."); 432d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 433d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 434d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!cur_token().IsScoperEqualTo(")")) { 435d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(open_paren_token, "Expected \")\" for expression", 436d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "I was looking for a \")\" corresponding to this one."); 437d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<ParseNode>(); 438d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 439d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; // Skip over ) 440d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ret.Pass(); 441d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 442d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 443d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// unary_expression := "!" expression 444d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<UnaryOpNode> Parser::ParseUnaryOp() { 445d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<UnaryOpNode> unary(new UnaryOpNode); 446d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 447d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(!at_end() && IsUnaryOperator(cur_token())); 448d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& op_token = cur_token(); 449d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch unary->set_op(op_token); 450d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cur_++; 451d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 452d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (at_end()) { 453d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err_ = Err(op_token, "Expected expression.", 454d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "This operator needs something to operate on."); 455d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<UnaryOpNode>(); 456d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 457d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch unary->set_operand(ParseExpression().Pass()); 458d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (has_error()) 459d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return scoped_ptr<UnaryOpNode>(); 460d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return unary.Pass(); 461d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 462d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 463d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochErr Parser::MakeEOFError(const std::string& message, 464d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& help) const { 465d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (tokens_.empty()) 466d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Err(Location(NULL, 1, 1), message, help); 467d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 468d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& last = tokens_[tokens_.size() - 1]; 469d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Err(last, message, help); 470d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 471