Allow global-scope declarations

Function-local scope is still WIP, but you can now define things outside of function blocks.
This commit is contained in:
Curle 2020-09-13 23:41:46 +01:00
parent a27d3dd782
commit 264c50509e
Signed by: TheCurle
GPG Key ID: 2F2E62F0DA69A5AE
8 changed files with 95 additions and 28 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
.idea
.vscode
out
bin

View File

@ -51,6 +51,7 @@ enum TokenTypes {
LI_RPARE, // )
LI_AMP, // &
LI_COM, // ,
TY_IDENTIFIER, // Identifier name. Variable, function, etc.
TY_NONE, // No return type. Literal void.
@ -229,14 +230,16 @@ struct ASTNode* ParsePrimary(void);
struct ASTNode* ParseStatement(void);
struct ASTNode* PrefixStatement();
struct ASTNode* ParseFunction();
void ParseGlobals();
struct ASTNode* ParseFunction(int Type);
struct ASTNode* ParseCompound();
struct ASTNode* CallFunction();
struct ASTNode* ReturnStatement();
int ParsePointer();
int ParseOptionalPointer();
int ValueAt(int Type);
int PointerTo(int Type);
@ -331,7 +334,7 @@ void AsFunctionEpilogue(int ID);
* * * * D E C L A R A T I O N * * * *
* * * * * * * * * * * * * * * * * * * * * * */
void BeginVariableDeclaration(void);
void BeginVariableDeclaration(int Type);
struct ASTNode* ParseIdentifier(void);
struct ASTNode* IfStatement();

View File

@ -223,6 +223,10 @@ int Tokenise(struct Token* Token) {
Token->type = LI_AMP;
break;
case ',':
Token->type = LI_COM;
break;
case '=':
Char = NextChar();
// If the next char is =, we have ==, the compare equality token.

View File

@ -79,14 +79,9 @@ int main(int argc, char* argv[]) {
AssemblerPreamble();
while(1) {
Node = ParseFunction();
printf("\nBeginning assembler creation of new function %s\n", Symbols[Node->Value.ID].Name);
AssembleTree(Node, -1, 0);
ParseGlobals();
if(CurrentToken.type == LI_EOF)
break;
}
//AsFunctionEpilogue();
//Node = ParsePrecedenceASTNode();
//printf("%d\n", ParseAST(Node));

View File

@ -333,7 +333,7 @@ struct ASTNode* CallFunction() {
* * * * * * * * * * * * * * * * * * * * * */
struct ASTNode* ParseStatement(void) {
int Type;
switch(CurrentToken.type) {
@ -344,7 +344,9 @@ struct ASTNode* ParseStatement(void) {
case TY_LONG:
case TY_INT:
printf("\t\tNew Variable: %s\n", CurrentIdentifier);
BeginVariableDeclaration();
Type = ParseOptionalPointer(CurrentToken.type);
VerifyToken(TY_IDENTIFIER, "ident");
BeginVariableDeclaration(Type);
return NULL;
case TY_IDENTIFIER:
@ -403,6 +405,38 @@ struct ASTNode* ParseCompound() {
}
}
void ParseGlobals() {
struct ASTNode* Tree;
int Type, FunctionComing;
printf("Parsing global definitions\n");
while(1) {
Type = ParseOptionalPointer();
//TODO: converge pathways on this block?
if(CurrentToken.type == KW_FUNC) {
VerifyToken(KW_FUNC, "::");
FunctionComing = 1;
}
VerifyToken(TY_IDENTIFIER, "ident");
if(FunctionComing && CurrentToken.type == LI_LPARE) {
printf("\tParsing function");
Tree = ParseFunction(Type);
printf("\nBeginning assembler creation of new function %s\n", Symbols[Tree->Value.ID].Name);
AssembleTree(Tree, -1, 0);
} else {
printf("\tParsing global variable declaration\n");
BeginVariableDeclaration(Type);
}
if(CurrentToken.type == LI_EOF)
break;
}
}
/* void ParseStatements() {

View File

@ -36,15 +36,16 @@ int ValueAt(int Type) {
return -1;
}
int ParsePointer() {
int ParseOptionalPointer() {
int Type;
// TODO: THIS IS WRONG AND SHOULD NOT EXIST
// TY_CHAR is 21, RET_CHAR is 1.
// TY_CHAR is 22, RET_CHAR is 1.
// Offset is 20. Rest are in order
if(CurrentToken.type >= TY_CHAR && CurrentToken.type <= TY_VOID) {
Type = CurrentToken.type - 20;
Type = CurrentToken.type - 21;
printf("\t\tConverting a %d type to a %d type.\n", CurrentToken.type, Type);
} else {
DieDecimal("Illegal type for pointerisation", CurrentToken.type);
}

View File

@ -126,29 +126,37 @@ int TypesCompatible(int* Left, int* Right, int STRICT) {
* //TODO: int i = 5;
*
*/
void BeginVariableDeclaration(void) {
void BeginVariableDeclaration(int Type) {
int ID;
int Type = ParsePointer(CurrentToken.type);
//printf("type: %s\n", Types[Type]);
VerifyToken(TY_IDENTIFIER, "ident");
while(1) {
//printf("Identifier: %s\n", CurrentIdentifier);
printf("Adding symbol %s of type %s.\n", CurrentIdentifier, TypeNames[Type]);
ID = AddSymbol(CurrentIdentifier, Type, ST_VAR);
AsNewSymb(ID);
VerifyToken(LI_SEMIC, ";");
if(CurrentToken.type == LI_SEMIC) {
printf("\tEnd of variables to declare in this statement\n");
Tokenise(&CurrentToken);
return;
}
if(CurrentToken.type == LI_COM) {
printf("\t\tStatement appears to continue. Integrating new variable.\n");
Tokenise(&CurrentToken);
VerifyToken(TY_IDENTIFIER, "ident");
continue;
}
DieDecimal("\nExpected ; after identifier, found", CurrentToken.type);
}
}
struct ASTNode* ParseFunction() {
struct ASTNode* ParseFunction(int Type) {
struct ASTNode* Tree;
struct ASTNode* FinalStatement;
int SymbolSlot, BreakLabel, Type;
Type = ParsePointer(CurrentToken.type);
VerifyToken(KW_FUNC, "::");
VerifyToken(TY_IDENTIFIER, "ident");
int SymbolSlot, BreakLabel;
printf("\nIdentified function %s\n", CurrentIdentifier);

16
tests/globals Normal file
View File

@ -0,0 +1,16 @@
int x, y;
int* z;
void :: main() {
int a, b, c;
b = 3; c = 8;
a = b + c * 10;
PrintInteger(a);
x = 12; PrintInteger(x);
z = &x;
y = *z;
PrintInteger(y);
}