Big cleanup and fixes.
We have pointer arithmetic!
This commit is contained in:
parent
d8abe6fec0
commit
bc1bac8a63
|
@ -30,10 +30,15 @@ static char* InvComparisons[6] = { "jne", "je", "jge", "jle", "jg", "j
|
|||
* * * * R O O T O F A S S E M B L E R * * * *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
static int Started = 0;
|
||||
|
||||
int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
|
||||
int LeftVal, RightVal;
|
||||
if(!Started)
|
||||
DumpTree(Node, 0);
|
||||
Started = 1;
|
||||
|
||||
printf("Current operation: %d\r\n", Node->Operation);
|
||||
switch(Node->Operation) {
|
||||
case OP_IF:
|
||||
return AsIf(Node);
|
||||
|
@ -102,10 +107,18 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
|
|||
return AsDeref(LeftVal, Node->Left->ExprType);
|
||||
|
||||
case OP_ASSIGN:
|
||||
return RightVal;
|
||||
printf("Calculating for assignment..\r\n");
|
||||
if(Node->Right == NULL)
|
||||
Die("Fault in assigning a null rvalue");
|
||||
switch(Node->Right->Operation) {
|
||||
case REF_IDENT: return AsStrVar(LeftVal, Node->Right->Value.ID);
|
||||
case OP_DEREF: return AsStrDeref(LeftVal, RightVal, Node->Right->ExprType);
|
||||
default: DieDecimal("Can't ASSIGN in AssembleTree: ", Node->Operation);
|
||||
}
|
||||
|
||||
case OP_WIDEN:
|
||||
return LeftVal;
|
||||
printf("\tWidening types..\r\n");
|
||||
return LeftVal; //AsWiden(LeftVal, Node->Left->ExprType, Node->ExprType);
|
||||
|
||||
case OP_RET:
|
||||
AsReturn(LeftVal, CurrentFunction);
|
||||
|
@ -146,14 +159,13 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
|
|||
|
||||
|
||||
case REF_IDENT:
|
||||
return AsLdVar(Node->Value.ID);
|
||||
|
||||
case LV_IDENT:
|
||||
return AsStrVar(Register, Node->Value.ID);
|
||||
if(Node->RVal || ParentOp == OP_DEREF)
|
||||
return AsLdVar(Node->Value.ID);
|
||||
else
|
||||
return -1;
|
||||
|
||||
case TERM_INTLITERAL:
|
||||
return AsLoad(Node->Value.IntValue);
|
||||
break;
|
||||
|
||||
case OP_PRINT:
|
||||
AssemblerPrint(LeftVal);
|
||||
|
@ -209,6 +221,7 @@ int NewLabel(void) {
|
|||
static int id = 1;
|
||||
return id++;
|
||||
}
|
||||
|
||||
|
||||
int AsIf(struct ASTNode* Node) {
|
||||
int FalseLabel, EndLabel;
|
||||
|
@ -439,11 +452,33 @@ int AsDeref(int Reg, int Type) {
|
|||
case PTR_LONG:
|
||||
fprintf(OutputFile, "\tmovq\t(%s), %s\n", Registers[Reg], Registers[Reg]);
|
||||
break;
|
||||
default:
|
||||
DieDecimal("Can't generate dereference for type", Type);
|
||||
}
|
||||
|
||||
return Reg;
|
||||
}
|
||||
|
||||
int AsStrDeref(int Register1, int Register2, int Type) {
|
||||
printf("\tStoring contents of %s into %s through a dereference, type %d\n", Registers[Register1], Registers[Register2], Type);
|
||||
|
||||
switch(Type) {
|
||||
case PTR_CHAR:
|
||||
fprintf(OutputFile, "\tmovb\t%s, (%s)\n", ByteRegisters[Register1], Registers[Register2]);
|
||||
break;
|
||||
case PTR_INT:
|
||||
fprintf(OutputFile, "\tmovq\t%s, (%s)\n", Registers[Register1], Registers[Register2]);
|
||||
break;
|
||||
case PTR_LONG:
|
||||
fprintf(OutputFile, "\tmovq\t%s, (%s)\n", Registers[Register1], Registers[Register2]);
|
||||
break;
|
||||
default:
|
||||
DieDecimal("Can't generate store-into-deref of type", Type);
|
||||
}
|
||||
|
||||
return Register1;
|
||||
}
|
||||
|
||||
void AsNewSymb(int ID) {
|
||||
int TypeSize;
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
|
||||
AddFunctionSymbol("PrintInteger", RET_CHAR, ST_FUNC, 0);
|
||||
//AddSymbol("forgecord", PTR_CHAR, ST_VAR);
|
||||
|
||||
Tokenise(&CurrentToken);
|
||||
|
||||
|
|
128
src/Parser.c
128
src/Parser.c
|
@ -18,12 +18,12 @@
|
|||
*
|
||||
*/
|
||||
static int Precedence[] =
|
||||
{ 0, // EOF
|
||||
10, 10, // + -
|
||||
20, 20, // * /
|
||||
30, 30, // =? !=
|
||||
40, 40, // < >
|
||||
40, 40}; // <= =>
|
||||
{ 0, 10, // EOF, ASSIGN
|
||||
20, 20, // + -
|
||||
30, 30, // * /
|
||||
40, 40, // =? !=
|
||||
50, 50, // < >
|
||||
50, 50}; // <= =>
|
||||
|
||||
static int OperatorPrecedence(int Token) {
|
||||
int Prec = Precedence[Token];
|
||||
|
@ -35,6 +35,10 @@ static int OperatorPrecedence(int Token) {
|
|||
return Prec;
|
||||
}
|
||||
|
||||
static int IsRightExpr(int Token) {
|
||||
return (Token == LI_EQUAL);
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* * * N O D E C O N S T R U C T I O N * * *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
@ -135,7 +139,7 @@ struct ASTNode* ParsePrimary(void) {
|
|||
break;
|
||||
|
||||
default:
|
||||
DieDecimal("Syntax Error", CurrentToken.type);
|
||||
DieDecimal("Unable to parse primary type", CurrentToken.type);
|
||||
}
|
||||
|
||||
Tokenise(&CurrentToken);
|
||||
|
@ -147,77 +151,102 @@ struct ASTNode* ParsePrimary(void) {
|
|||
struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
|
||||
struct ASTNode* LeftNode, *RightNode;
|
||||
struct ASTNode* LeftTemp, *RightTemp;
|
||||
int LeftType, RightType;
|
||||
// int LeftType, RightType;
|
||||
int NodeType, OpType;
|
||||
|
||||
LeftNode = PrefixStatement();
|
||||
|
||||
NodeType = CurrentToken.type;
|
||||
if(NodeType == LI_SEMIC || NodeType == LI_RPARE)
|
||||
return LeftNode;
|
||||
|
||||
//printf("Current token has value %d, type %d\n", CurrentToken.value, CurrentToken.type);
|
||||
while(OperatorPrecedence(NodeType) > PreviousTokenPrecedence) {
|
||||
if(NodeType == LI_SEMIC || NodeType == LI_RPARE) {
|
||||
LeftNode->RVal = 1; return LeftNode;
|
||||
}
|
||||
|
||||
printf("Current token has value %d, type %d\n", CurrentToken.value, CurrentToken.type);
|
||||
while((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) || (IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) {
|
||||
//printf("inside while\n");
|
||||
Tokenise(&CurrentToken);
|
||||
|
||||
RightNode = ParsePrecedenceASTNode(Precedence[NodeType]);
|
||||
|
||||
/*
|
||||
LeftType = LeftNode->ExprType;
|
||||
RightType = RightNode->ExprType;
|
||||
|
||||
*/
|
||||
/**
|
||||
* While parsing this node, we may need to widen some types.
|
||||
* This requires a few functions and checks.
|
||||
*/
|
||||
|
||||
OpType = ParseTokenToOperation(NodeType);
|
||||
LeftTemp = MutateType(LeftNode, RightType, OpType);
|
||||
RightTemp = MutateType(RightNode, LeftType, OpType);
|
||||
|
||||
/**
|
||||
* If both are null, the types are incompatible.
|
||||
*/
|
||||
if(OpType == OP_ASSIGN) {
|
||||
RightNode->RVal = 1;
|
||||
|
||||
if(LeftTemp == NULL && RightTemp == NULL)
|
||||
Die("Incompatible types in parsing nodes");
|
||||
RightNode = MutateType(RightNode, LeftNode->ExprType, 0);
|
||||
if(LeftNode == NULL)
|
||||
Die("Incompatible Expression encountered in assignment");
|
||||
|
||||
printf("\tAssigning variable: %s\n", Symbols[FindSymbol(CurrentIdentifier)].Name);
|
||||
printf("\tAfter parsing, the identifier name is %s, id %d in the symbol table.\n", CurrentIdentifier, FindSymbol(CurrentIdentifier));
|
||||
|
||||
/**
|
||||
* If the left was valid, or valid for
|
||||
* expansion, then it will be non-null.
|
||||
*
|
||||
* If it was valid, then this will be
|
||||
* equivalent to LeftNode = LeftNode
|
||||
*/
|
||||
LeftTemp = LeftNode;
|
||||
LeftNode = RightNode;
|
||||
RightNode = LeftTemp;
|
||||
} else {
|
||||
LeftNode->RVal = 1;
|
||||
RightNode->RVal = 1;
|
||||
|
||||
if(LeftTemp)
|
||||
LeftNode = LeftTemp;
|
||||
printf("mutate left\r\n");
|
||||
LeftTemp = MutateType(LeftNode, RightNode->ExprType, OpType);
|
||||
printf("mutate right\r\n");
|
||||
RightTemp = MutateType(RightNode, LeftNode->ExprType, OpType);
|
||||
printf("mutate right over\r\n");
|
||||
/**
|
||||
* If both are null, the types are incompatible.
|
||||
*/
|
||||
|
||||
if(LeftTemp == NULL && RightTemp == NULL)
|
||||
Die("Incompatible types in parsing nodes");
|
||||
|
||||
/**
|
||||
* If the left was valid, or valid for
|
||||
* expansion, then it will be non-null.
|
||||
*
|
||||
* If it was valid, then this will be
|
||||
* equivalent to LeftNode = LeftNode
|
||||
*/
|
||||
|
||||
/**
|
||||
* Same here, but there is a higher chance
|
||||
* for the right node to be incompatible due
|
||||
* to the nature of widening types.
|
||||
*/
|
||||
|
||||
if(RightTemp)
|
||||
RightNode = RightTemp;
|
||||
if(LeftTemp)
|
||||
LeftNode = LeftTemp;
|
||||
|
||||
/**
|
||||
* Same here, but there is a higher chance
|
||||
* for the right node to be incompatible due
|
||||
* to the nature of widening types.
|
||||
*/
|
||||
|
||||
if(RightTemp)
|
||||
RightNode = RightTemp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks over, back to normal parsing.
|
||||
*/
|
||||
|
||||
/*
|
||||
if(LeftType)
|
||||
LeftNode = ConstructASTBranch(LeftType, RightNode->ExprType, LeftNode, 0);
|
||||
if(RightType)
|
||||
RightNode = ConstructASTBranch(RightType, LeftNode->ExprType, RightNode, 0);
|
||||
|
||||
*/
|
||||
LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode, 0);
|
||||
|
||||
NodeType = CurrentToken.type;
|
||||
if(NodeType == LI_SEMIC || NodeType == LI_RPARE)
|
||||
if(NodeType == LI_SEMIC || NodeType == LI_RPARE) {
|
||||
LeftNode->RVal = 1;
|
||||
return LeftNode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LeftNode->RVal = 1;
|
||||
return LeftNode;
|
||||
}
|
||||
|
||||
|
@ -349,27 +378,23 @@ struct ASTNode* ParseStatement(void) {
|
|||
int Type;
|
||||
|
||||
switch(CurrentToken.type) {
|
||||
|
||||
case KW_PRINT:
|
||||
return PrintStatement();
|
||||
|
||||
case TY_CHAR:
|
||||
case TY_LONG:
|
||||
case TY_INT:
|
||||
printf("\t\tNew Variable: %s\n", CurrentIdentifier);
|
||||
Type = ParseOptionalPointer(CurrentToken.type);
|
||||
Type = ParseOptionalPointer();
|
||||
VerifyToken(TY_IDENTIFIER, "ident");
|
||||
BeginVariableDeclaration(Type);
|
||||
return NULL;
|
||||
|
||||
case TY_IDENTIFIER:
|
||||
/*case TY_IDENTIFIER:
|
||||
if(Symbols[FindSymbol(CurrentIdentifier)].Structure == ST_FUNC)
|
||||
printf("\t\tCalling Function: %s\n", Symbols[FindSymbol(CurrentIdentifier)].Name);
|
||||
else
|
||||
printf("\t\tAssigning variable: %s\n", Symbols[FindSymbol(CurrentIdentifier)].Name);
|
||||
|
||||
return ParseIdentifier();
|
||||
|
||||
*/
|
||||
case KW_IF:
|
||||
return IfStatement();
|
||||
|
||||
|
@ -383,7 +408,8 @@ struct ASTNode* ParseStatement(void) {
|
|||
return ReturnStatement();
|
||||
|
||||
default:
|
||||
DieDecimal("Syntax Error in single-statement parsing. Token:", CurrentToken.type);
|
||||
ParsePrecedenceASTNode(0);
|
||||
//DieDecimal("Syntax Error in single-statement parsing. Token:", CurrentToken.type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -101,17 +101,20 @@ struct ASTNode* ReturnStatement() {
|
|||
|
||||
Tree = ParsePrecedenceASTNode(0);
|
||||
|
||||
/*
|
||||
ReturnType = Tree->ExprType;
|
||||
FunctionType = Symbols[CurrentFunction].Type;
|
||||
*/
|
||||
|
||||
Tree = MutateType(Tree, FunctionType, 0);
|
||||
if(!Tree)
|
||||
Tree = MutateType(Tree, Symbols[CurrentFunction].Type, 0);
|
||||
if(Tree == NULL)
|
||||
Die("Returning a value of incorrect type for function");
|
||||
|
||||
|
||||
/*
|
||||
if(ReturnType)
|
||||
Tree = ConstructASTBranch(ReturnType, FunctionType, Tree, 0);
|
||||
|
||||
*/
|
||||
|
||||
Tree = ConstructASTBranch(OP_RET, RET_NONE, Tree, 0);
|
||||
|
||||
printf("\t\tReturning from function %s\n", Symbols[CurrentFunction].Name);
|
||||
|
@ -136,6 +139,7 @@ struct ASTNode* ReturnStatement() {
|
|||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
struct ASTNode* ParseIdentifier() {
|
||||
struct ASTNode* Left, *Right, *Tree;
|
||||
int LeftType, RightType;
|
||||
|
@ -171,7 +175,7 @@ struct ASTNode* ParseIdentifier() {
|
|||
Tree = ConstructASTNode(OP_ASSIGN, RET_INT, Left, NULL, Right, 0);
|
||||
|
||||
return Tree;
|
||||
}
|
||||
}*/
|
||||
|
||||
struct ASTNode* IfStatement() {
|
||||
struct ASTNode* Condition, *True, *False = NULL;
|
||||
|
@ -306,13 +310,13 @@ struct ASTNode* PrefixStatement() {
|
|||
|
||||
if(Tree->Operation != REF_IDENT && Tree->Operation != OP_DEREF)
|
||||
Die("* must be followed by another * or an identifier.");
|
||||
|
||||
|
||||
Tree = ConstructASTBranch(OP_DEREF, ValueAt(Tree->ExprType), Tree, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
Tree = ParsePrimary();
|
||||
|
||||
|
||||
}
|
||||
|
||||
return Tree;
|
||||
|
|
14
tests/pointers2
Normal file
14
tests/pointers2
Normal file
|
@ -0,0 +1,14 @@
|
|||
int c;
|
||||
int d;
|
||||
int *e;
|
||||
int f;
|
||||
|
||||
int :: main() {
|
||||
c= 12;
|
||||
d=18;
|
||||
PrintInteger(c);
|
||||
e= &c + 1;
|
||||
f= *e;
|
||||
PrintInteger(f);
|
||||
return(0);
|
||||
}
|
Loading…
Reference in New Issue
Block a user