From 0c6c034c486e76b6b4e7b0f98ab3b2ff02e6a08d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 12 Aug 2006 18:12:45 +0000 Subject: [PATCH] Two fixes: 1. Allow argument list of a call to be empty. 2. Handle expressions in a statement context that start with an identifier. These are nasty to handle due to the 'label:' production which requires having two tokens of look-ahead, or by having tricky code (which we choose to do). llvm-svn: 38887 --- clang/Parse/ParseExpr.cpp | 44 ++++++++++++++++++++++++++---- clang/Parse/ParseStmt.cpp | 14 ++++++++-- clang/include/clang/Parse/Parser.h | 1 + 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/clang/Parse/ParseExpr.cpp b/clang/Parse/ParseExpr.cpp index b38397533a9a..d1a4af7bc4ec 100644 --- a/clang/Parse/ParseExpr.cpp +++ b/clang/Parse/ParseExpr.cpp @@ -195,7 +195,8 @@ Parser::ExprResult Parser::ParseExpression() { return ParseRHSOfBinaryExpression(LHS, prec::Comma); } -// Expr that doesn't include commas. +/// ParseAssignmentExpression - Parse an expr that doesn't include commas. +/// Parser::ExprResult Parser::ParseAssignmentExpression() { ExprResult LHS = ParseCastExpression(false); if (LHS.isInvalid) return LHS; @@ -203,6 +204,35 @@ Parser::ExprResult Parser::ParseAssignmentExpression() { return ParseRHSOfBinaryExpression(LHS, prec::Assignment); } +/// ParseExpressionWithLeadingIdentifier - This special purpose method is used +/// in contexts where we have already consumed an identifier (which we saved in +/// 'Tok'), then discovered that the identifier was really the leading token of +/// part of an expression. For example, in "A[1]+B", we consumed "A" (which is +/// now in 'Tok') and the current token is "[". +Parser::ExprResult Parser:: +ParseExpressionWithLeadingIdentifier(const LexerToken &Tok) { + // We know that 'Tok' must correspond to this production: + // primary-expression: identifier + + // TODO: Pass 'Tok' to the action. + ExprResult Res = ExprResult(false); + + // Because we have to parse an entire cast-expression before starting the + // ParseRHSOfBinaryExpression method (which parses any trailing binops), we + // need to handle the 'postfix-expression' rules. We do this by invoking + // ParsePostfixExpressionSuffix to consume any postfix-expression suffixes: + Res = ParsePostfixExpressionSuffix(Res); + if (Res.isInvalid) return Res; + + // At this point, the "A[1]" part of "A[1]+B" has been consumed. Once this is + // done, we know we don't have to do anything for cast-expression, because the + // only non-postfix-expression production starts with a '(' token, and we know + // we have an identifier. As such, we can invoke ParseRHSOfBinaryExpression + // to consume any trailing operators (e.g. "+" in this example) and connected + // chunks of the expression. + return ParseRHSOfBinaryExpression(Res, prec::Comma); +} + /// ParseRHSOfBinaryExpression - Parse a binary expression that starts with /// LHS and has a precedence of at least MinPrec. Parser::ExprResult @@ -476,11 +506,13 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { Loc = Tok.getLocation(); ConsumeParen(); - while (1) { - ParseAssignmentExpression(); - if (Tok.getKind() != tok::comma) - break; - ConsumeToken(); // Next argument. + if (Tok.getKind() != tok::r_paren) { + while (1) { + ParseAssignmentExpression(); + if (Tok.getKind() != tok::comma) + break; + ConsumeToken(); // Next argument. + } } // Match the ')'. diff --git a/clang/Parse/ParseStmt.cpp b/clang/Parse/ParseStmt.cpp index 909af64b644a..696631878abd 100644 --- a/clang/Parse/ParseStmt.cpp +++ b/clang/Parse/ParseStmt.cpp @@ -185,6 +185,7 @@ void Parser::ParseIdentifierStatement(bool OnlyStatement) { IdentifierInfo *II = Tok.getIdentifierInfo(); assert(Tok.getKind() == tok::identifier && II && "Not an identifier!"); + LexerToken IdentTok = Tok; // Save the token. ConsumeToken(); // eat the identifier. // identifier ':' statement @@ -211,9 +212,16 @@ void Parser::ParseIdentifierStatement(bool OnlyStatement) { return; } - // Otherwise, this is an expression. Seed it with II. - - assert(0); + // Otherwise, this is an expression. Seed it with II and parse it. + ExprResult Res = ParseExpressionWithLeadingIdentifier(IdentTok); + if (Res.isInvalid) + SkipUntil(tok::semi); + else if (Tok.getKind() == tok::semi) + ConsumeToken(); + else { + Diag(Tok, diag::err_expected_semi_after, "expression"); + SkipUntil(tok::semi); + } } /// ParseCaseStatement diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 84fe2e70350a..00021fa878c0 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -178,6 +178,7 @@ private: //===--------------------------------------------------------------------===// // C99 6.5: Expressions. //ExprResult ParseExpression(); // Above. + ExprResult ParseExpressionWithLeadingIdentifier(const LexerToken &Tok); ExprResult ParseAssignmentExpression(); // Expr that doesn't include commas. ExprResult ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec);