diff --git a/parse.c b/parse.c index 399d552..8e90689 100644 --- a/parse.c +++ b/parse.c @@ -677,37 +677,47 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueTyp void ParseDeclaration(struct ParseState *Parser, enum LexToken Token) { char *Identifier; + struct ValueType *BasicType; struct ValueType *Typ; struct Value *CValue; - TypeParse(Parser, &Typ, &Identifier); - if (Token == TokenVoidType && Identifier != StrEmpty) - ProgramFail(Parser, "can't define a void variable"); - - if ((Token != TokenVoidType && Token != TokenStructType && Token != TokenUnionType) && Identifier == StrEmpty) - ProgramFail(Parser, "identifier expected"); - - if (Identifier != StrEmpty) + TypeParseFront(Parser, &BasicType); + do { - /* handle function definitions */ - if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket) - ParseFunctionDefinition(Parser, Typ, Identifier, FALSE); - else + TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier); + if (Token == TokenVoidType && Identifier != StrEmpty) + ProgramFail(Parser, "can't define a void variable"); + + if ((Token != TokenVoidType && Token != TokenStructType && Token != TokenUnionType) && Identifier == StrEmpty) + ProgramFail(Parser, "identifier expected"); + + if (Identifier != StrEmpty) { - if (LexGetToken(Parser, NULL, FALSE) != TokenAssign) - VariableDefine(Parser, Identifier, VariableAllocValueFromType(Parser, Typ, TRUE, NULL)); + /* handle function definitions */ + if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket) + ParseFunctionDefinition(Parser, Typ, Identifier, FALSE); else - { /* we're assigning an initial value */ - LexGetToken(Parser, NULL, TRUE); - if (!ParseExpression(Parser, &CValue)) - ProgramFail(Parser, "expression expected"); - - VariableDefine(Parser, Identifier, CValue); - if (Parser->Mode == RunModeRun) - VariableStackPop(Parser, CValue); + { + if (LexGetToken(Parser, NULL, FALSE) != TokenAssign) + VariableDefine(Parser, Identifier, VariableAllocValueFromType(Parser, Typ, TRUE, NULL)); + else + { /* we're assigning an initial value */ + LexGetToken(Parser, NULL, TRUE); + if (!ParseExpression(Parser, &CValue)) + ProgramFail(Parser, "expression expected"); + + VariableDefine(Parser, Identifier, CValue); + if (Parser->Mode == RunModeRun) + VariableStackPop(Parser, CValue); + } } } - } + + Token = LexGetToken(Parser, NULL, FALSE); + if (Token == TokenComma) + LexGetToken(Parser, NULL, TRUE); + + } while (Token == TokenComma); } /* parse a #define macro definition and store it for later */ diff --git a/picoc.h b/picoc.h index dae0dc5..bec4c91 100644 --- a/picoc.h +++ b/picoc.h @@ -270,6 +270,8 @@ void TypeInit(); int TypeSize(struct ValueType *Typ, int ArraySize); int TypeSizeValue(struct Value *Val); int TypeStackSizeValue(struct Value *Val); +int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ); +void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier); void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier); struct ValueType *TypeGetMatching(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier); diff --git a/tests/00_assignment.c b/tests/00_assignment.c index accfd0e..b174ab0 100644 --- a/tests/00_assignment.c +++ b/tests/00_assignment.c @@ -5,3 +5,6 @@ printf("%d\n", a); int b = 64; printf("%d\n", b); +int c = 12, d = 34; +printf("%d, %d\n", c, d); + diff --git a/tests/00_assignment.expect b/tests/00_assignment.expect index abb11cc..d4407f3 100644 --- a/tests/00_assignment.expect +++ b/tests/00_assignment.expect @@ -1,2 +1,3 @@ 42 64 +12, 34 diff --git a/type.c b/type.c index 51c0c88..3f29546 100644 --- a/type.c +++ b/type.c @@ -175,14 +175,43 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt LexGetToken(Parser, NULL, TRUE); } -/* parse a type */ -void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier) +/* parse a type - just the basic type */ +int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ) +{ + struct ParseState Before = *Parser; + enum LexToken Token = LexGetToken(Parser, NULL, TRUE); + *Typ = NULL; + + switch (Token) + { + case TokenIntType: case TokenLongType: case TokenShortType: *Typ = &IntType; break; + case TokenCharType: *Typ = &CharType; break; +#ifndef NO_FP + case TokenFloatType: case TokenDoubleType: *Typ = &FPType; break; +#endif + case TokenVoidType: *Typ = &VoidType; break; + + case TokenStructType: case TokenUnionType: + if (*Typ != NULL) + ProgramFail(Parser, "bad type declaration"); + + TypeParseStruct(Parser, Typ, Token == TokenStructType); + break; + + default: *Parser = Before; return FALSE; + } + + return TRUE; +} + +/* parse a type - the part which is repeated with each identifier in a declaration list */ +void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier) { struct ParseState Before; enum LexToken Token; struct Value *LexValue; int Done = FALSE; - *Typ = NULL; + *Typ = BasicTyp; *Identifier = StrEmpty; while (!Done) @@ -191,20 +220,6 @@ void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identif Token = LexGetToken(Parser, &LexValue, TRUE); switch (Token) { - case TokenIntType: case TokenLongType: case TokenShortType: *Typ = &IntType; break; - case TokenCharType: *Typ = &CharType; break; -#ifndef NO_FP - case TokenFloatType: case TokenDoubleType: *Typ = &FPType; break; -#endif - case TokenVoidType: *Typ = &VoidType; break; - - case TokenStructType: case TokenUnionType: - if (*Typ != NULL) - ProgramFail(Parser, "bad type declaration"); - - TypeParseStruct(Parser, Typ, Token == TokenStructType); - break; - case TokenOpenBracket: if (*Typ != NULL) ProgramFail(Parser, "bad type declaration"); @@ -266,3 +281,13 @@ void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identif } } } + +/* parse a type - a complete declaration including identifier */ +void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier) +{ + struct ValueType *BasicType; + + TypeParseFront(Parser, &BasicType); + TypeParseIdentPart(Parser, BasicType, Typ, Identifier); +} +