diff --git a/parse.c b/parse.c index cc41ec8..25071d9 100644 --- a/parse.c +++ b/parse.c @@ -350,6 +350,7 @@ int ParseStatement(struct ParseState *Parser) case TokenVoidType: case TokenStructType: case TokenUnionType: + case TokenEnumType: *Parser = PreState; ParseDeclaration(Parser, Token); break; diff --git a/picoc.h b/picoc.h index 0c91ce2..4da8df1 100644 --- a/picoc.h +++ b/picoc.h @@ -115,7 +115,7 @@ struct ValueType struct ValueType *FromType; /* the type we're derived from (or NULL) */ struct ValueType *DerivedTypeList; /* first in a list of types derived from this one */ struct ValueType *Next; /* next item in the derived type list */ - struct Table *Members; /* members of a struct, union or enum */ + struct Table *Members; /* members of a struct or union */ }; /* function definition */ @@ -170,7 +170,6 @@ struct Value char ValOnHeap; /* the AnyValue is on the heap (but this Value is on the stack) */ char ValOnStack; /* the AnyValue is on the stack along with this Value */ char IsLValue; /* is modifiable and is allocated somewhere we can usefully modify it */ - char TempToken; /* temporary token used in expression evaluation */ }; /* hash table data structure */ diff --git a/platform_support.c b/platform_support.c index 745cbe6..ffee4d0 100644 --- a/platform_support.c +++ b/platform_support.c @@ -4,6 +4,7 @@ /* get a line of interactive input */ char *PlatformGetLine(char *Buf, int MaxLen) { + fflush(stdout); return fgets(Buf, MaxLen, stdin); } diff --git a/tests/17_enum.c b/tests/17_enum.c new file mode 100644 index 0000000..b2aff27 --- /dev/null +++ b/tests/17_enum.c @@ -0,0 +1,18 @@ +enum fred +{ + a, + b, + c, + d, + e = 54, + f = 73, + g, + h +} frod; + +printf("%d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h); +printf("%d\n", frod); +frod = 12; +printf("%d\n", frod); +frod = e; +printf("%d\n", frod); diff --git a/tests/17_enum.expect b/tests/17_enum.expect new file mode 100644 index 0000000..0c17a2d --- /dev/null +++ b/tests/17_enum.expect @@ -0,0 +1,4 @@ +0 1 2 3 54 73 74 75 +0 +12 +54 diff --git a/tests/Makefile b/tests/Makefile index 16294ed..ee27957 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -12,7 +12,8 @@ TESTS= 00_assignment.test \ 12_hashdefine.test \ 13_integer_literals.test \ 14_if.test \ - 16_nesting.test + 16_nesting.test \ + 17_enum.test %.test: %.expect %.c @echo Test: $*... diff --git a/type.c b/type.c index 9ec3c34..940ff02 100644 --- a/type.c +++ b/type.c @@ -175,6 +175,60 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt LexGetToken(Parser, NULL, TRUE); } +/* parse an enum declaration */ +void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ) +{ + struct Value *LexValue; + struct Value InitValue; + enum LexToken Token; + struct ValueType *EnumType; + int EnumValue = 0; + char *EnumIdentifier; + + if (TopStackFrame != NULL) + ProgramFail(Parser, "enum definitions can only be globals"); + + if (LexGetToken(Parser, &LexValue, TRUE) != TokenIdentifier) + ProgramFail(Parser, "enum name required"); + + *Typ = &IntType; + EnumType = TypeGetMatching(Parser, &UberType, TypeEnum, 0, LexValue->Val->Identifier); + Token = LexGetToken(Parser, NULL, FALSE); + if (Token != TokenLeftBrace) + { /* use the already defined enum */ + if ((*Typ)->Members == NULL) + ProgramFail(Parser, "enum '%s' isn't defined", LexValue->Val->Identifier); + + return; + } + + LexGetToken(Parser, NULL, TRUE); + (*Typ)->Members = &GlobalTable; + memset(&InitValue, '\0', sizeof(struct Value)); + InitValue.Typ = &IntType; + InitValue.Val = (union AnyValue *)&EnumValue; + do { + if (LexGetToken(Parser, &LexValue, TRUE) != TokenIdentifier) + ProgramFail(Parser, "identifier expected"); + + EnumIdentifier = LexValue->Val->Identifier; + if (LexGetToken(Parser, NULL, FALSE) == TokenAssign) + { + LexGetToken(Parser, NULL, TRUE); + EnumValue = ExpressionParseInt(Parser); + } + + VariableDefine(Parser, EnumIdentifier, &InitValue); + + Token = LexGetToken(Parser, NULL, TRUE); + if (Token != TokenComma && Token != TokenRightBrace) + ProgramFail(Parser, "comma expected"); + + EnumValue++; + + } while (Token == TokenComma); +} + /* parse a type - just the basic type */ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ) { @@ -198,6 +252,13 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ) TypeParseStruct(Parser, Typ, Token == TokenStructType); break; + case TokenEnumType: + if (*Typ != NULL) + ProgramFail(Parser, "bad type declaration"); + + TypeParseEnum(Parser, Typ); + break; + default: *Parser = Before; return FALSE; }