diff --git a/clang/Parse/ParseExpr.cpp b/clang/Parse/ParseExpr.cpp new file mode 100644 index 000000000000..7d4e4b04ffd0 --- /dev/null +++ b/clang/Parse/ParseExpr.cpp @@ -0,0 +1,51 @@ +//===--- Expression.cpp - Expression Parsing ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Expression parsing implementation. +// +//===----------------------------------------------------------------------===// + +#include "clang/Parse/Parser.h" +#include "clang/Basic/Diagnostic.h" +using namespace llvm; +using namespace clang; + +Parser::ExprTy Parser::ParseExpression() { + if (Tok.getKind() == tok::numeric_constant) { + ConsumeToken(); + return 0; + } + + Diag(Tok, diag::err_parse_error); + return 0; +} + +///primary-expression: +/// identifier +/// constant +/// string-literal +/// '(' expression ')' + +/// ParseParenExpression - C99 c.5.1p5 +/// primary-expression: +/// '(' expression ')' +void Parser::ParseParenExpression() { + assert(Tok.getKind() == tok::l_paren && "Not a paren expr!"); + SourceLocation OpenLoc = Tok.getLocation(); + ConsumeParen(); + + ParseExpression(); + + if (Tok.getKind() == tok::r_paren) { + ConsumeParen(); + } else { + Diag(Tok, diag::err_expected_rparen); + Diag(OpenLoc, diag::err_matching); + } +} diff --git a/clang/Parse/ParseStmt.cpp b/clang/Parse/ParseStmt.cpp index e04d7af3fbd5..9008f3ece565 100644 --- a/clang/Parse/ParseStmt.cpp +++ b/clang/Parse/ParseStmt.cpp @@ -67,19 +67,29 @@ using namespace clang; /// [OBC] '@' 'throw' expression ';' [TODO] /// [OBC] '@' 'throw' ';' [TODO] /// -void Parser::ParseStatementOrDeclaration() { +void Parser::ParseStatementOrDeclaration(bool OnlyStatement) { switch (Tok.getKind()) { default: Diag(Tok, diag::err_expected_statement_declaration); SkipUntil(tok::semi); break; - case tok::semi: // expression[opt] ';' -> expression isn't present. - ConsumeToken(); - break; - case tok::l_brace: // compound-statement -> '{}' block + // C99 6.8.2: compound-statement -> '{}' block + case tok::l_brace: ParseCompoundStatement(); break; + // C99 6.8.3: expression[opt] ';' + case tok::semi: + ConsumeToken(); + break; + + // C99 6.8.4.1: if-statement + case tok::kw_if: + ParseIfStatement(); + break; + + + // TODO: Handle OnlyStatement.. } } @@ -114,7 +124,7 @@ void Parser::ParseCompoundStatement() { ConsumeBrace(); // eat the '{'. while (Tok.getKind() != tok::r_brace && Tok.getKind() != tok::eof) - ParseStatementOrDeclaration(); + ParseStatementOrDeclaration(false); // We broke out of the while loop because we found a '}' or EOF. if (Tok.getKind() == tok::r_brace) @@ -122,3 +132,33 @@ void Parser::ParseCompoundStatement() { else Diag(Tok, diag::err_expected_rbrace); } + +/// ParseIfStatement +/// if-statement: [C99 6.8.4.1] +/// 'if' '(' expression ')' statement +/// 'if' '(' expression ')' statement 'else' statement +void Parser::ParseIfStatement() { + assert(Tok.getKind() == tok::kw_if && "Not an if stmt!"); + ConsumeToken(); // eat the 'if'. + + if (Tok.getKind() != tok::l_paren) { + Diag(Tok, diag::err_expected_lparen_after_if, "if"); + SkipUntil(tok::semi); + return; + } + + // Parse the condition. + ParseParenExpression(); + + // Read the if condition. + ParseStatement(); + + // If it has an else, parse it. + if (Tok.getKind() == tok::kw_else) { + ConsumeToken(); + ParseStatement(); + } + +} + + diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index c0757e2b1300..c99c8eb56d91 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ DE06BECB0A854E4B0050E87E /* Scope.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06BECA0A854E4B0050E87E /* Scope.h */; }; DE06BEF40A8558200050E87E /* Decl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06BEF30A8558200050E87E /* Decl.h */; }; DE06CC180A899E110050E87E /* Statement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE06CC170A899E110050E87E /* Statement.cpp */; }; + DE06CEC00A8AE7800050E87E /* Expression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE06CEBF0A8AE7800050E87E /* Expression.cpp */; }; DE1F22030A7D852A00FBF588 /* Parser.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F22020A7D852A00FBF588 /* Parser.h */; }; DE1F22200A7D879000FBF588 /* ParserActions.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F221F0A7D879000FBF588 /* ParserActions.h */; }; DE1F24700A7DC99000FBF588 /* Actions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE1F246D0A7DC99000FBF588 /* Actions.cpp */; }; @@ -116,6 +117,7 @@ DE06BECA0A854E4B0050E87E /* Scope.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Scope.h; path = clang/Parse/Scope.h; sourceTree = ""; }; DE06BEF30A8558200050E87E /* Decl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Decl.h; path = clang/Parse/Decl.h; sourceTree = ""; }; DE06CC170A899E110050E87E /* Statement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Statement.cpp; path = Parse/Statement.cpp; sourceTree = ""; }; + DE06CEBF0A8AE7800050E87E /* Expression.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Expression.cpp; path = Parse/Expression.cpp; sourceTree = ""; }; DE1F22020A7D852A00FBF588 /* Parser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Parser.h; path = clang/Parse/Parser.h; sourceTree = ""; }; DE1F221F0A7D879000FBF588 /* ParserActions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ParserActions.h; path = clang/Parse/ParserActions.h; sourceTree = ""; }; DE1F246D0A7DC99000FBF588 /* Actions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Actions.cpp; path = Parse/Actions.cpp; sourceTree = ""; }; @@ -227,6 +229,7 @@ children = ( DE1F246D0A7DC99000FBF588 /* Actions.cpp */, DE1F257A0A7DD86800FBF588 /* Declarations.cpp */, + DE06CEBF0A8AE7800050E87E /* Expression.cpp */, DE1F246E0A7DC99000FBF588 /* Parse.cpp */, DE1F246F0A7DC99000FBF588 /* ParseDeclarations.cpp */, DE06BEC80A854E390050E87E /* Scope.cpp */, @@ -386,6 +389,7 @@ DE1F257B0A7DD86800FBF588 /* Declarations.cpp in Sources */, DE06BEC90A854E390050E87E /* Scope.cpp in Sources */, DE06CC180A899E110050E87E /* Statement.cpp in Sources */, + DE06CEC00A8AE7800050E87E /* Expression.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 2ec05ddf60f2..68b406c1bb21 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -274,6 +274,8 @@ DIAG(err_expected_after_declarator, ERROR, "expected '=', ',', ';', 'asm', or '__attribute__' after declarator") DIAG(err_expected_statement_declaration, ERROR, "expected statement or declaration") +DIAG(err_expected_lparen_after_if, ERROR, + "expected '(' after '%s'") /// err_matching - this is used as a continuation of a previous error, e.g. to /// specify the '(' when we expected a ')'. This should probably be some diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index daec73bf2de0..c3233a77304d 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -158,14 +158,21 @@ private: //===--------------------------------------------------------------------===// // C99 6.8: Statements and Blocks. - void ParseStatementOrDeclaration(); + void ParseStatement() { ParseStatementOrDeclaration(true); } + void ParseStatementOrDeclaration(bool OnlyStatement = false); void ParseCompoundStatement(); + void ParseIfStatement(); //===--------------------------------------------------------------------===// // C99 6.7: Declarations. void ParseDeclarationSpecifiers(DeclSpec &DS); bool isDeclarationSpecifier() const; + //===--------------------------------------------------------------------===// + // C99 6.5: Expressions. + //ExprTy ParseExpression(); // Above. + void ParseParenExpression(); + /// ParseDeclarator - Parse and verify a newly-initialized declarator. void ParseDeclarator(Declarator &D); void ParseDeclaratorInternal(Declarator &D);