Implement alias - a faster typedef

This commit is contained in:
Curle 2022-03-04 02:31:16 +00:00
parent 628c7a3a13
commit 2c87817904
5 changed files with 123 additions and 8 deletions

View File

@ -253,7 +253,8 @@ enum DataTypes {
DAT_STRUCT = 80, // Struct Data DAT_STRUCT = 80, // Struct Data
DAT_UNION, // Union 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(); void BeginEnumDeclaration();
int ReadAlias(struct SymbolTableEntry** Composite);
int ParseAlias(char* Name, struct SymbolTableEntry** Composite);
struct ASTNode* GetExpressionList(); struct ASTNode* GetExpressionList();
struct ASTNode* CallFunction(); struct ASTNode* CallFunction();
@ -396,6 +401,8 @@ struct SymbolTableEntry* FindGlobal(char* Symbol);
struct SymbolTableEntry* FindStruct(char* Symbol); struct SymbolTableEntry* FindStruct(char* Symbol);
struct SymbolTableEntry* FindAlias(char* Symbol);
struct SymbolTableEntry* FindEnum(char* Symbol); struct SymbolTableEntry* FindEnum(char* Symbol);
struct SymbolTableEntry* FindEnumMember(char* Symbol); struct SymbolTableEntry* FindEnumMember(char* Symbol);

View File

@ -135,8 +135,7 @@ struct ASTNode* ConstructASTLeaf(int Operation, int Type, struct SymbolTableEntr
* @param IntValue: The integer value encoded by this Node, if applicable. * @param IntValue: The integer value encoded by this Node, if applicable.
* @return a newly constructed AST Node * @return a newly constructed AST Node
*/ */
struct ASTNode* struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue) {
ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue) {
return ConstructASTNode(Operation, Type, Left, NULL, NULL, Symbol, IntValue); return ConstructASTNode(Operation, Type, Left, NULL, NULL, Symbol, IntValue);
} }
@ -159,6 +158,64 @@ int ParseTokenToOperation(int Token) {
DieDecimal("ParseToken: Unknown token", 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: * Primary expressions may be any one of:
* * A terminal integer literal * * A terminal integer literal
@ -215,7 +272,7 @@ struct ASTNode* ParsePrimary(void) {
* the order of operations is upheld, that the precedence of the prior * the order of operations is upheld, that the precedence of the prior
* iteration is considered, and that every error is handled. * 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 * type mismatches and widening are handled properly, and that all parsing
* is over by the time the end tokens ") } ] ;" are encountered. * is over by the time the end tokens ") } ] ;" are encountered.
* *
@ -534,7 +591,7 @@ void ParseGlobals() {
// Structs are parsed fully in ParseOptionalPointer // Structs are parsed fully in ParseOptionalPointer
// TODO: FIX THAT!! // 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(); Tokenise();
continue; continue;
} }

View File

@ -92,9 +92,13 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
Type = RET_LONG; Type = RET_LONG;
Tokenise(); Tokenise();
break; break;
case KW_STRUCT: case TY_IDENTIFIER:
Type = DAT_STRUCT; Type = ParseAlias(CurrentIdentifier, Composite);
*Composite = BeginCompositeDeclaration(Type); break;
case KW_ALIAS:
Type = ReadAlias(Composite);
if (CurrentToken.type == LI_SEMIC)
Type = DAT_ALIAS;
break; break;
case KW_ENUM: case KW_ENUM:
Type = RET_INT; Type = RET_INT;
@ -102,6 +106,10 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
if (CurrentToken.type == LI_SEMIC) if (CurrentToken.type == LI_SEMIC)
Type = DAT_ENUM; Type = DAT_ENUM;
break; break;
case KW_STRUCT:
Type = DAT_STRUCT;
*Composite = BeginCompositeDeclaration(Type);
break;
case KW_UNION: case KW_UNION:
Type = DAT_UNION; Type = DAT_UNION;
*Composite = BeginCompositeDeclaration(Type); *Composite = BeginCompositeDeclaration(Type);

View File

@ -143,6 +143,17 @@ struct SymbolTableEntry* FindEnumMember(char* Symbol) {
return SearchList(Symbol, EnumMembers); 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. * An override for FindSymbol.
* Searches only the defined Unions. * Searches only the defined Unions.
@ -257,6 +268,9 @@ struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Stor
case SC_ENUM: case SC_ENUM:
AppendSymbol(&Enums, &EnumsEnd, Node); AppendSymbol(&Enums, &EnumsEnd, Node);
break; break;
case SC_ALIAS:
AppendSymbol(&Types, &TypesEnd, Node);
break;
case SC_ENUMENTRY: case SC_ENUMENTRY:
AppendSymbol(&EnumMembers, &EnumMembersEnd, Node); AppendSymbol(&EnumMembers, &EnumMembersEnd, Node);
break; break;

29
tests/alias.er Normal file
View File

@ -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);
}