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