Begin cleanup of array parsing

TODO: debug segfault
This commit is contained in:
Curle 2020-11-19 02:31:40 +00:00
parent 985f02723e
commit 999f8dc267
Signed by: TheCurle
GPG Key ID: 5942F13718443F79
5 changed files with 62 additions and 24 deletions

View File

@ -257,6 +257,7 @@ int ParseOptionalPointer();
int ValueAt(int Type); int ValueAt(int Type);
int PointerTo(int Type); int PointerTo(int Type);
struct ASTNode* AccessArray();
int ParseTokenToOperation(int Token); int ParseTokenToOperation(int Token);

View File

@ -15,6 +15,7 @@ int TypeSizes[9] = { 0, 1, 4, 8, 0, 8, 8,
char* TokenStrings[] = { "+", "-", "*", "/", "int" }; char* TokenStrings[] = { "+", "-", "*", "/", "int" };
char* TokenNames[] = { char* TokenNames[] = {
"End of file", "End of file",
"Equivalency",
"Addition", "Addition",
"Subtraction", "Subtraction",
@ -28,17 +29,20 @@ char* TokenNames[] = {
"Less Than or Equal", "Less Than or Equal",
"Greater Than or Equal", "Greater Than or Equal",
"Assignment",
"Integer literal", "Integer literal",
"Statement End", "Statement End",
"Compound Block Start", "Compound Block Start",
"Compound Block End", "Compound Block End",
"Array index start",
"Array index end",
"Logical Block Start", "Logical Block Start",
"Logical Block End", "Logical Block End",
"Dereference operator", "Dereference operator",
"Comma",
"Identifier", "Identifier",
"None Type", "None Type",
@ -103,16 +107,16 @@ void Die(char* Error) {
} }
void DieMessage(char* Error, char* Reason) { void DieMessage(char* Error, char* Reason) {
fprintf(stderr, "%s:%s on line %d\n", Error, Reason, Line); fprintf(stderr, "%s: %s on line %d\n", Error, Reason, Line);
exit(1); exit(1);
} }
void DieDecimal(char* Error, int Number) { void DieDecimal(char* Error, int Number) {
fprintf(stderr, "%s:%d on line %d\n", Error, Number, Line); fprintf(stderr, "%s: %d on line %d\n", Error, Number, Line);
exit(1); exit(1);
} }
void DieChar(char* Error, int Char) { void DieChar(char* Error, int Char) {
fprintf(stderr, "%s:%c on line %d\n", Error, Char, Line); fprintf(stderr, "%s: %c on line %d\n", Error, Char, Line);
exit(1); exit(1);
} }

View File

@ -28,8 +28,8 @@ static int Precedence[] =
static int OperatorPrecedence(int Token) { static int OperatorPrecedence(int Token) {
int Prec = Precedence[Token]; int Prec = Precedence[Token];
if(Prec == 0) { if(Prec == 0 || Token >= RET_VOID) {
Die("Attempting to determine operator precedence of an EOF or INT literal."); DieMessage("Attempting to determine operator precedence of an EOF or INT literal", TokenNames[Token]);
} }
return Prec; return Prec;
@ -114,8 +114,6 @@ struct ASTNode* ParsePrimary(void) {
Node = ConstructASTLeaf(TERM_INTLITERAL, RET_CHAR, CurrentToken.value); Node = ConstructASTLeaf(TERM_INTLITERAL, RET_CHAR, CurrentToken.value);
else else
Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, CurrentToken.value); Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, CurrentToken.value);
//Tokenise(&CurrentToken); // Fetch next token
break; break;
case TY_IDENTIFIER: case TY_IDENTIFIER:
@ -128,9 +126,11 @@ struct ASTNode* ParsePrimary(void) {
if(CurrentToken.type == LI_LPARE) if(CurrentToken.type == LI_LPARE)
return CallFunction(); return CallFunction();
if(CurrentToken.type == LI_LBRAS)
return AccessArray();
// Otherwise, we've read too far and need to go back. // Otherwise, we've read too far and need to go back.
RejectToken(&CurrentToken); RejectToken(&CurrentToken);
// It's a variable, so find the symbol and construct a leaf for it // It's a variable, so find the symbol and construct a leaf for it
ID = FindSymbol(CurrentIdentifier); ID = FindSymbol(CurrentIdentifier);
if(ID == -1) if(ID == -1)
@ -138,24 +138,18 @@ struct ASTNode* ParsePrimary(void) {
Node = ConstructASTLeaf(REF_IDENT, Symbols[ID].Type, ID); Node = ConstructASTLeaf(REF_IDENT, Symbols[ID].Type, ID);
break; break;
case LI_LPARE: case LI_RPARE:
// We're expecting a primary encased in parentheses. // Starting a ( expr ) block
// That means, we tokenise the next item
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
// Then, we expect a valid expression
Node = ParsePrecedenceASTNode(0); Node = ParsePrecedenceASTNode(0);
// Then, after the expression is parsed, we're returned here. // Make sure we close
// since the expression is ENCASED in parens, we expect another.
VerifyToken(LI_RPARE, ")"); VerifyToken(LI_RPARE, ")");
// Skip the next tokenise and return early
return Node; return Node;
default:
DieDecimal("Unable to parse primary type", CurrentToken.type);
} }
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
return Node; return Node;
@ -171,11 +165,13 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
LeftNode = PrefixStatement(); LeftNode = PrefixStatement();
NodeType = CurrentToken.type; NodeType = CurrentToken.type;
if(NodeType == LI_SEMIC || NodeType == LI_RPARE) { printf("%d\r\n", CurrentToken.type);
if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) {
printf("Current token matches ; ) ]\r\n");
LeftNode->RVal = 1; return LeftNode; LeftNode->RVal = 1; return LeftNode;
} }
printf("Current token has value %d, type %d\n", CurrentToken.value, CurrentToken.type); printf("Current token has value %d, type %s\n", CurrentToken.value, TokenNames[CurrentToken.type]);
while((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) || (IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) { while((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) || (IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) {
//printf("inside while\n"); //printf("inside while\n");
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
@ -254,7 +250,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
*/ */
LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode, 0); LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode, 0);
NodeType = CurrentToken.type; NodeType = CurrentToken.type;
if(NodeType == LI_SEMIC || NodeType == LI_RPARE) { if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) {
LeftNode->RVal = 1; LeftNode->RVal = 1;
return LeftNode; return LeftNode;
} }

View File

@ -65,3 +65,30 @@ int ParseOptionalPointer() {
return Type; return Type;
} }
struct ASTNode* AccessArray() {
struct ASTNode* LeftNode, *RightNode;
int ID;
printf("\tAccessing array %s as requested\r\n", CurrentIdentifier);
if ((ID = FindSymbol(CurrentIdentifier)) == -1 || Symbols[ID].Structure != ST_ARR)
DieMessage("Accessing undeclared array", CurrentIdentifier);
LeftNode = ConstructASTLeaf(OP_ADDRESS, Symbols[ID].Type, ID);
printf("\t\tCurrent token: %s\r\n", TokenNames[CurrentToken.type]);
Tokenise(&CurrentToken);
printf("\t\tCurrent token: %s\r\n", TokenNames[CurrentToken.type]);
RightNode = ParsePrecedenceASTNode(0);
VerifyToken(LI_RBRAS, "]");
if(!TypeIsInt(RightNode->ExprType))
Die("Array index is not integer");
RightNode = MutateType(RightNode, LeftNode->ExprType, OP_ADD);
LeftNode = ConstructASTNode(OP_ADD, Symbols[ID].Type, LeftNode, NULL, RightNode, 0);
LeftNode = ConstructASTBranch(OP_DEREF, ValueAt(LeftNode->ExprType), LeftNode, 0);
return LeftNode;
}

10
tests/arrays1 Normal file
View File

@ -0,0 +1,10 @@
int a;
int b[25];
int :: main() {
b[3] = 12;
a = b[3];
PrintInteger(a);
PrintInteger(b[5]);
return(0);
}