Refactor init-declarator-list parsing code to allow for-statements to have

initializers in them.

llvm-svn: 38847
This commit is contained in:
Chris Lattner 2006-08-10 05:19:57 +00:00
parent 9075bd7727
commit 53361ac130
6 changed files with 77 additions and 72 deletions

View File

@ -20,6 +20,60 @@ using namespace clang;
// C99 6.7: Declarations.
//===----------------------------------------------------------------------===//
/// ParseDeclaration - Parse a full 'declaration', which consists of
/// declaration-specifiers, some number of declarators, and a semicolon.
/// 'Context' should be a Declarator::TheContext value.
void Parser::ParseDeclaration(unsigned Context) {
// Parse the common declaration-specifiers piece.
DeclSpec DS;
ParseDeclarationSpecifiers(DS);
Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
ParseDeclarator(DeclaratorInfo);
ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
}
void Parser::ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
// At this point, we know that it is not a function definition. Parse the
// rest of the init-declarator-list.
while (1) {
// must be: decl-spec[opt] declarator init-declarator-list
// Parse declarator '=' initializer.
if (Tok.getKind() == tok::equal) {
ConsumeToken();
// FIXME: THIS IS WRONG!!
ParseExpression();
}
// TODO: install declarator.
// If we don't have a comma, it is either the end of the list (a ';') or an
// error, bail out.
if (Tok.getKind() != tok::comma)
break;
// Consume the comma.
ConsumeToken();
// Parse the next declarator.
D.clear();
ParseDeclarator(D);
}
if (Tok.getKind() == tok::semi) {
ConsumeToken();
} else {
Diag(Tok, diag::err_parse_error);
// Skip to end of block or statement
SkipUntil(tok::r_brace, true);
if (Tok.getKind() == tok::semi)
ConsumeToken();
}
}
/// ParseDeclarationSpecifiers
/// declaration-specifiers: [C99 6.7]
/// storage-class-specifier declaration-specifiers [opt]

View File

@ -14,6 +14,7 @@
#include "clang/Parse/Parser.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Parse/Declarations.h"
using namespace llvm;
using namespace clang;
@ -262,20 +263,21 @@ void Parser::ParseForStatement() {
// Parse the first part of the for specifier.
if (Tok.getKind() == tok::semi) { // for (;
// no first part.
// no first part, eat the ';'.
ConsumeToken();
} else if (isDeclarationSpecifier()) { // for (int X = 4;
// FIXME: Parse declaration.
assert(0);
// Parse declaration, which eats the ';'.
ParseDeclaration(Declarator::ForContext);
} else {
ParseExpression();
}
if (Tok.getKind() == tok::semi) {
ConsumeToken();
} else {
Diag(Tok, diag::err_expected_semi_for);
Diag(ForLoc, diag::err_matching);
SkipUntil(tok::semi);
if (Tok.getKind() == tok::semi) {
ConsumeToken();
} else {
Diag(Tok, diag::err_expected_semi_for);
Diag(ForLoc, diag::err_matching);
SkipUntil(tok::semi);
}
}
// Parse the second part of the for specifier.

View File

@ -191,6 +191,7 @@ void Parser::ParseDeclarationOrFunctionDefinition() {
ParseDeclarationSpecifiers(DS);
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
// declaration-specifiers init-declarator-list[opt] ';'
if (Tok.getKind() == tok::semi)
assert(0 && "Unimp!");
@ -230,39 +231,8 @@ void Parser::ParseDeclarationOrFunctionDefinition() {
return;
}
// At this point, we know that it is not a function definition. Parse the
// rest of the init-declarator-list.
while (1) {
// must be: decl-spec[opt] declarator init-declarator-list
// Parse declarator '=' initializer.
if (Tok.getKind() == tok::equal)
assert(0 && "cannot handle initializer yet!");
// TODO: install declarator.
// If we don't have a comma, it is either the end of the list (a ';') or an
// error, bail out.
if (Tok.getKind() != tok::comma)
break;
// Consume the comma.
ConsumeToken();
// Parse the next declarator.
DeclaratorInfo.clear();
ParseDeclarator(DeclaratorInfo);
}
if (Tok.getKind() == tok::semi) {
ConsumeToken();
} else {
Diag(Tok, diag::err_parse_error);
// Skip to end of block or statement
SkipUntil(tok::r_brace, true);
if (Tok.getKind() == tok::semi)
ConsumeToken();
}
// Parse the init-declarator-list for a normal declaration.
ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
}
/// ParseFunctionDefinition - We parsed and verified that the specified
@ -282,33 +252,8 @@ void Parser::ParseFunctionDefinition(Declarator &D) {
// int foo(a,b) int a; float b; {}
if (!FnTypeInfo.Fun.hasPrototype && !FnTypeInfo.Fun.isEmpty) {
// Read all the argument declarations.
while (isDeclarationSpecifier()) {
// Parse the common declaration-specifiers piece.
DeclSpec DS;
ParseDeclarationSpecifiers(DS);
Declarator DeclaratorInfo(DS, Declarator::FileContext);
ParseDeclarator(DeclaratorInfo);
while (Tok.getKind() == tok::comma) {
// Consume the comma.
ConsumeToken();
// Parse the next declarator.
DeclaratorInfo.clear();
ParseDeclarator(DeclaratorInfo);
}
if (Tok.getKind() == tok::semi) {
ConsumeToken();
} else {
Diag(Tok, diag::err_expected_semi_knr_fn_body);
// Skip to end of block or statement
SkipUntil(tok::l_brace, true);
if (Tok.getKind() == tok::semi)
ConsumeToken();
}
}
while (isDeclarationSpecifier())
ParseDeclaration(Declarator::KNRTypeListContext);
// Note, check that we got them all.
} else {

View File

@ -266,8 +266,8 @@ DIAG(err_expected_rparen, ERROR,
"expected ')'")
DIAG(err_expected_rbrace, ERROR,
"expected '}' to end compound statement ('{}' block)")
DIAG(err_expected_semi_knr_fn_body, ERROR,
"expected ';' at end of K&R-style function argument declaration list")
DIAG(err_expected_semi_decl_list, ERROR,
"expected ';' at end of declaration list")
DIAG(err_expected_fn_body, ERROR,
"expected function body after function declarator")
DIAG(err_expected_after_declarator, ERROR,

View File

@ -169,6 +169,9 @@ private:
//===--------------------------------------------------------------------===//
// C99 6.7: Declarations.
void ParseDeclaration(unsigned Context);
void ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
void ParseDeclarationSpecifiers(DeclSpec &DS);
bool isDeclarationSpecifier() const;

View File

@ -15,4 +15,5 @@ int test2() {
for (;;)
for (9;0;2)
;
for (int X = 0; 0; 0);
}