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