From 628c7a3a13e566f0c012a39c63a565c49046bd66 Mon Sep 17 00:00:00 2001 From: Curle Date: Fri, 4 Mar 2022 01:11:04 +0000 Subject: [PATCH] Implement enums and the foundation of a type alias system --- include/Data.h | 2 ++ include/Defs.h | 19 ++++++++++--- src/Lexer.c | 7 +++++ src/Main.c | 2 ++ src/Parser.c | 2 +- src/Pointers.c | 6 ++++ src/Statements.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++- src/Symbols.c | 29 ++++++++++++++++++++ tests/enum.er | 18 ++++++++++++ 9 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 tests/enum.er diff --git a/include/Data.h b/include/Data.h index 2c83a5f..e3e484f 100644 --- a/include/Data.h +++ b/include/Data.h @@ -22,9 +22,11 @@ extern_ struct SymbolTableEntry* Params, * ParamsEnd; extern_ struct SymbolTableEntry* Structs, * StructsEnd; extern_ struct SymbolTableEntry* CompositeMembers, * CompositeMembersEnd; +extern_ struct SymbolTableEntry* EnumMembers, * EnumMembersEnd; extern_ struct SymbolTableEntry* Unions, * UnionsEnd; extern_ struct SymbolTableEntry* Enums, * EnumsEnd; +extern_ struct SymbolTableEntry* Types, * TypesEnd; extern_ bool OptDumpTree; extern_ bool OptKeepAssembly; diff --git a/include/Defs.h b/include/Defs.h index 65baf0e..26adf31 100644 --- a/include/Defs.h +++ b/include/Defs.h @@ -97,7 +97,9 @@ enum TokenTypes { KW_FOR, KW_RETURN, KW_STRUCT, - KW_UNION + KW_UNION, + KW_ENUM, + KW_ALIAS }; /* @@ -222,7 +224,9 @@ enum StorageScope { SC_STRUCT, // Struct Definitions SC_UNION, // Union Definitions SC_ENUM, // Enum Definitions - SC_MEMBER, // The members of Structs or Enums + SC_ENUMENTRY, // Enum Entry Names + SC_ALIAS, // Typedef aliases + SC_MEMBER, // The members of Structs or Unions //SC_CLASS, // Class-local definitions //SC_STATIC, // Static storage definitions SC_PARAM, // Function parameters @@ -249,6 +253,7 @@ enum DataTypes { DAT_STRUCT = 80, // Struct Data DAT_UNION, // Union Data + DAT_ENUM = -1, // Enum Data }; /* @@ -260,8 +265,8 @@ enum StructureType { ST_VAR, // This is variable ST_FUNC, // This is a function ST_ARR, // This is an array - ST_RUCT // This is a struct - // This is an enum + ST_RUCT, // This is a struct + ST_ENUM, // This is an enum // This is a typedef }; @@ -352,6 +357,8 @@ struct ASTNode* ParseCompound(); struct SymbolTableEntry* BeginCompositeDeclaration(int Type); +void BeginEnumDeclaration(); + struct ASTNode* GetExpressionList(); struct ASTNode* CallFunction(); @@ -389,6 +396,10 @@ struct SymbolTableEntry* FindGlobal(char* Symbol); struct SymbolTableEntry* FindStruct(char* Symbol); +struct SymbolTableEntry* FindEnum(char* Symbol); + +struct SymbolTableEntry* FindEnumMember(char* Symbol); + struct SymbolTableEntry* FindUnion(char* Symbol); struct SymbolTableEntry* FindMember(char* Symbol); diff --git a/src/Lexer.c b/src/Lexer.c index 8c98620..1b3adae 100644 --- a/src/Lexer.c +++ b/src/Lexer.c @@ -283,6 +283,11 @@ static int ReadKeyword(char* Str) { return KW_FUNC; break; + case 'a': + if (!strcmp(Str, "alias")) + return KW_ALIAS; + break; + case 'c': if (!strcmp(Str, "char")) return TY_CHAR; @@ -291,6 +296,8 @@ static int ReadKeyword(char* Str) { case 'e': if (!strcmp(Str, "else")) return KW_ELSE; + if (!strcmp(Str, "enum")) + return KW_ENUM; break; diff --git a/src/Main.c b/src/Main.c index 5476df9..32c7c12 100644 --- a/src/Main.c +++ b/src/Main.c @@ -89,6 +89,8 @@ char* ScopeNames[] = { "STRUCT", "UNION", "ENUM", + "ENUM_ENTRY", + "ALIAS", "MEMBER", "PARAMETER", "LOCAL" diff --git a/src/Parser.c b/src/Parser.c index 0a35880..cca74f7 100644 --- a/src/Parser.c +++ b/src/Parser.c @@ -534,7 +534,7 @@ void ParseGlobals() { // Structs are parsed fully in ParseOptionalPointer // TODO: FIX THAT!! - if ((Type == DAT_STRUCT || Type == DAT_UNION) && CurrentToken.type == LI_SEMIC) { + if ((Type == DAT_STRUCT || Type == DAT_UNION || Type == DAT_ENUM) && CurrentToken.type == LI_SEMIC) { Tokenise(); continue; } diff --git a/src/Pointers.c b/src/Pointers.c index 06a0ca9..203430c 100644 --- a/src/Pointers.c +++ b/src/Pointers.c @@ -96,6 +96,12 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) { Type = DAT_STRUCT; *Composite = BeginCompositeDeclaration(Type); break; + case KW_ENUM: + Type = RET_INT; + BeginEnumDeclaration(); + if (CurrentToken.type == LI_SEMIC) + Type = DAT_ENUM; + break; case KW_UNION: Type = DAT_UNION; *Composite = BeginCompositeDeclaration(Type); diff --git a/src/Statements.c b/src/Statements.c index 71ac8c0..f789e02 100644 --- a/src/Statements.c +++ b/src/Statements.c @@ -94,7 +94,7 @@ struct SymbolTableEntry* BeginCompositeDeclaration(int Type) { if (Composite) DieMessage("Redefinition of composite", CurrentIdentifier); - Composite = AddSymbol(CurrentIdentifier, Type, 0, Type == DAT_STRUCT ? SC_STRUCT : SC_UNION, 0, 0, NULL); + Composite = AddSymbol(CurrentIdentifier, Type, ST_RUCT, Type == DAT_STRUCT ? SC_STRUCT : SC_UNION, 0, 0, NULL); Tokenise(); printf("Reading a composite declaration.. Type is %s\n", Type == DAT_STRUCT ? "struct" : "union"); ReadDeclarationList(NULL, SC_MEMBER, LI_RBRAC); @@ -123,6 +123,69 @@ struct SymbolTableEntry* BeginCompositeDeclaration(int Type) { return Composite; } +void BeginEnumDeclaration() { + struct SymbolTableEntry* Type = NULL; + char* Name; + int Value = 0; + + Tokenise(); + + // enum name + if (CurrentToken.type == TY_IDENTIFIER) { + Type = FindEnum(CurrentIdentifier); + Name = strdup(CurrentIdentifier); + Tokenise(); + } + + // enum name {? if not, enum name var. + if (CurrentToken.type != LI_LBRAC) { + if (Type == NULL) + DieMessage("Undeclared Enum", Name); + + return; + } + + // Skip the { that we have + Tokenise(); + + if (Type != NULL) + DieMessage("Attempting to redefine enum", Type->Name); + else + Type = AddSymbol(Name, DAT_ENUM, ST_ENUM, SC_ENUM, 0, 0, NULL); + + while (1) { + VerifyToken(TY_IDENTIFIER, "Enum Entry"); + Name = strdup(CurrentIdentifier); + + Type = FindEnumMember(Name); + if (Type != NULL) + DieMessage("Attempting to redeclare enum value", Name); + + // Parse equality + if (CurrentToken.type == LI_EQUAL) { + Tokenise(); + // Expect a number after the equals + if (CurrentToken.type != LI_INT) + Die("Expected integer to assign enum value to"); + Value = CurrentToken.value; + Tokenise(); + } + + Type = AddSymbol(Name, DAT_ENUM, ST_ENUM, SC_ENUMENTRY, Value++, 0, NULL); + + // Break on right brace + if (CurrentToken.type == LI_RBRAC) + break; + + VerifyToken(LI_COM, "Comma"); + } + + // Skip right brace + Tokenise(); + + +} + /* * Handles the declaration of a type of a variable. * int newVar; @@ -502,6 +565,12 @@ struct ASTNode* PostfixStatement() { struct ASTNode* Tree; struct SymbolTableEntry* Entry; + // Early exit if we find an enum value + if ((Entry = FindEnumMember(CurrentIdentifier)) != NULL) { + Tokenise(); + return ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, Entry->IntValue); + } + Tokenise(); if (CurrentToken.type == LI_LPARE) diff --git a/src/Symbols.c b/src/Symbols.c index a7cacfd..4878d4a 100644 --- a/src/Symbols.c +++ b/src/Symbols.c @@ -120,6 +120,29 @@ struct SymbolTableEntry* FindGlobal(char* Symbol) { struct SymbolTableEntry* FindStruct(char* Symbol) { return SearchList(Symbol, Structs); } + +/* + * An override for FindSymbol. + * Searches only the defined Enums. + * @param Symbol: The string name of the symbol to search for. + * @return a pointer to the node if found, else NULL + * + */ +struct SymbolTableEntry* FindEnum(char* Symbol) { + return SearchList(Symbol, Enums); +} + +/* + * An override for FindSymbol. + * Searches only the defined enum members. + * @param Symbol: The string name of the symbol to search for. + * @return a pointer to the node if found, else NULL + * + */ +struct SymbolTableEntry* FindEnumMember(char* Symbol) { + return SearchList(Symbol, EnumMembers); +} + /* * An override for FindSymbol. * Searches only the defined Unions. @@ -231,6 +254,12 @@ struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Stor case SC_UNION: AppendSymbol(&Unions, &UnionsEnd, Node); break; + case SC_ENUM: + AppendSymbol(&Enums, &EnumsEnd, Node); + break; + case SC_ENUMENTRY: + AppendSymbol(&EnumMembers, &EnumMembersEnd, Node); + break; case SC_MEMBER: AppendSymbol(&CompositeMembers, &CompositeMembersEnd, Node); break; diff --git a/tests/enum.er b/tests/enum.er new file mode 100644 index 0000000..e04b5c4 --- /dev/null +++ b/tests/enum.er @@ -0,0 +1,18 @@ +int :: printf(char* format); + +enum fruit { apple, pear, shallot }; + +enum basket { + abc = 15, + def +}; + +enum basket thing; +enum fruit stuff; + +int :: main() { + int temp; + temp = apple + pear + abc; + printf("%d\n", temp); + return (0); +} \ No newline at end of file