diff --git a/include/Defs.h b/include/Defs.h index 26adf31..dd39821 100644 --- a/include/Defs.h +++ b/include/Defs.h @@ -253,7 +253,8 @@ enum DataTypes { DAT_STRUCT = 80, // Struct Data DAT_UNION, // Union Data - DAT_ENUM = -1, // Enum Data + DAT_ENUM, // Enum Data + DAT_ALIAS, // Alias Definition }; /* @@ -359,6 +360,10 @@ struct SymbolTableEntry* BeginCompositeDeclaration(int Type); void BeginEnumDeclaration(); +int ReadAlias(struct SymbolTableEntry** Composite); + +int ParseAlias(char* Name, struct SymbolTableEntry** Composite); + struct ASTNode* GetExpressionList(); struct ASTNode* CallFunction(); @@ -396,6 +401,8 @@ struct SymbolTableEntry* FindGlobal(char* Symbol); struct SymbolTableEntry* FindStruct(char* Symbol); +struct SymbolTableEntry* FindAlias(char* Symbol); + struct SymbolTableEntry* FindEnum(char* Symbol); struct SymbolTableEntry* FindEnumMember(char* Symbol); diff --git a/src/Parser.c b/src/Parser.c index cca74f7..77cfc72 100644 --- a/src/Parser.c +++ b/src/Parser.c @@ -135,8 +135,7 @@ struct ASTNode* ConstructASTLeaf(int Operation, int Type, struct SymbolTableEntr * @param IntValue: The integer value encoded by this Node, if applicable. * @return a newly constructed AST Node */ -struct ASTNode* -ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue) { +struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue) { return ConstructASTNode(Operation, Type, Left, NULL, NULL, Symbol, IntValue); } @@ -159,6 +158,64 @@ int ParseTokenToOperation(int Token) { DieDecimal("ParseToken: Unknown token", Token); } +/* + * The "alias" keyword allows one to create a new keyword that is accepted in lieu of another (or a chain of another) + * It does this by reading in sequence: + * * The "alias" keyword + * * The thing to alias (any valid primary type) + * * The new name + * + * They are stored in a separate symbol table and can be used anywhere the original is valid. + */ +int ReadAlias(struct SymbolTableEntry** Composite) { + int Type; + + Tokenise(); + + Type = ParseOptionalPointer(Composite); + + if (FindAlias(CurrentIdentifier) != NULL) + DieMessage("Redefinition of type", CurrentIdentifier); + + AddSymbol(CurrentIdentifier, Type, ST_VAR, SC_ALIAS, 0, 0, *Composite); + Tokenise(); + + return Type; +} + +/** + * When using an alias, we need to lookup the name (possibly recursively) to check whether it is a valid alias. + * If so, we need to know what it is an alias of. + * Once we have resolved what it finally means, we return the type. + * @param Name The name of the (initial) alias to check + * @param Composite A pointer to the composite element we should fill in. + * @return The aliased type. + */ +int ParseAlias(char* Name, struct SymbolTableEntry** Composite) { + struct SymbolTableEntry* Type = NULL, *RootType = NULL; + + // Ensure the first-round alias exists + Type = FindAlias(Name); + if (Type == NULL) + DieMessage("Unknown alias", Name); + + // Loop on the alias for as long as it continues to exist. + while (true) { + if (Type->CompositeType == NULL) + break; + + RootType = FindAlias(Type->CompositeType->Name); + if (RootType == NULL) + break; + Type = RootType; + } + + Tokenise(); + *Composite = Type->CompositeType; + return Type->Type; + +} + /* * Primary expressions may be any one of: * * A terminal integer literal @@ -215,7 +272,7 @@ struct ASTNode* ParsePrimary(void) { * the order of operations is upheld, that the precedence of the prior * iteration is considered, and that every error is handled. * - * This is where all of the right-associative statements are folded, where + * This is where all the right-associative statements are folded, where * type mismatches and widening are handled properly, and that all parsing * is over by the time the end tokens ") } ] ;" are encountered. * @@ -534,7 +591,7 @@ void ParseGlobals() { // Structs are parsed fully in ParseOptionalPointer // TODO: FIX THAT!! - if ((Type == DAT_STRUCT || Type == DAT_UNION || Type == DAT_ENUM) && CurrentToken.type == LI_SEMIC) { + if ((Type == DAT_STRUCT || Type == DAT_UNION || Type == DAT_ENUM || Type == DAT_ALIAS) && CurrentToken.type == LI_SEMIC) { Tokenise(); continue; } diff --git a/src/Pointers.c b/src/Pointers.c index 203430c..31b7cee 100644 --- a/src/Pointers.c +++ b/src/Pointers.c @@ -92,9 +92,13 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) { Type = RET_LONG; Tokenise(); break; - case KW_STRUCT: - Type = DAT_STRUCT; - *Composite = BeginCompositeDeclaration(Type); + case TY_IDENTIFIER: + Type = ParseAlias(CurrentIdentifier, Composite); + break; + case KW_ALIAS: + Type = ReadAlias(Composite); + if (CurrentToken.type == LI_SEMIC) + Type = DAT_ALIAS; break; case KW_ENUM: Type = RET_INT; @@ -102,6 +106,10 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) { if (CurrentToken.type == LI_SEMIC) Type = DAT_ENUM; break; + case KW_STRUCT: + Type = DAT_STRUCT; + *Composite = BeginCompositeDeclaration(Type); + break; case KW_UNION: Type = DAT_UNION; *Composite = BeginCompositeDeclaration(Type); diff --git a/src/Symbols.c b/src/Symbols.c index 4878d4a..d215d18 100644 --- a/src/Symbols.c +++ b/src/Symbols.c @@ -143,6 +143,17 @@ struct SymbolTableEntry* FindEnumMember(char* Symbol) { return SearchList(Symbol, EnumMembers); } +/* + * 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* FindAlias(char* Symbol) { + return SearchList(Symbol, Types); +} + /* * An override for FindSymbol. * Searches only the defined Unions. @@ -257,6 +268,9 @@ struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Stor case SC_ENUM: AppendSymbol(&Enums, &EnumsEnd, Node); break; + case SC_ALIAS: + AppendSymbol(&Types, &TypesEnd, Node); + break; case SC_ENUMENTRY: AppendSymbol(&EnumMembers, &EnumMembersEnd, Node); break; diff --git a/tests/alias.er b/tests/alias.er new file mode 100644 index 0000000..990d02f --- /dev/null +++ b/tests/alias.er @@ -0,0 +1,29 @@ +int :: printf(char* format); + +alias int water; +water drink; + +struct fruit { + int x, + int y +}; + +alias struct fruit basket; +basket food; + +alias basket shop; +shop market; + +int :: main() { + drink = 5; + printf("%d\n", drink); + + food.x = 10; + food.y = 66; + printf("%d\n", food.y); + + market.y = 150; + printf("%d\n", market.y); + + return (0); +} \ No newline at end of file