diff --git a/include/Defs.h b/include/Defs.h index 7e7deae..a933165 100644 --- a/include/Defs.h +++ b/include/Defs.h @@ -257,6 +257,7 @@ int ParseOptionalPointer(); int ValueAt(int Type); int PointerTo(int Type); +struct ASTNode* AccessArray(); int ParseTokenToOperation(int Token); diff --git a/src/Main.c b/src/Main.c index edda6ab..aff0f0e 100644 --- a/src/Main.c +++ b/src/Main.c @@ -15,6 +15,7 @@ int TypeSizes[9] = { 0, 1, 4, 8, 0, 8, 8, char* TokenStrings[] = { "+", "-", "*", "/", "int" }; char* TokenNames[] = { "End of file", + "Equivalency", "Addition", "Subtraction", @@ -28,17 +29,20 @@ char* TokenNames[] = { "Less Than or Equal", "Greater Than or Equal", - "Assignment", "Integer literal", "Statement End", "Compound Block Start", "Compound Block End", + "Array index start", + "Array index end", + "Logical Block Start", "Logical Block End", "Dereference operator", + "Comma", "Identifier", "None Type", @@ -103,16 +107,16 @@ void Die(char* Error) { } 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); } 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); } 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); } \ No newline at end of file diff --git a/src/Parser.c b/src/Parser.c index 13f8ef2..fdb0c0b 100644 --- a/src/Parser.c +++ b/src/Parser.c @@ -28,8 +28,8 @@ static int Precedence[] = static int OperatorPrecedence(int Token) { int Prec = Precedence[Token]; - if(Prec == 0) { - Die("Attempting to determine operator precedence of an EOF or INT literal."); + if(Prec == 0 || Token >= RET_VOID) { + DieMessage("Attempting to determine operator precedence of an EOF or INT literal", TokenNames[Token]); } return Prec; @@ -114,8 +114,6 @@ struct ASTNode* ParsePrimary(void) { Node = ConstructASTLeaf(TERM_INTLITERAL, RET_CHAR, CurrentToken.value); else Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, CurrentToken.value); - - //Tokenise(&CurrentToken); // Fetch next token break; case TY_IDENTIFIER: @@ -128,9 +126,11 @@ struct ASTNode* ParsePrimary(void) { if(CurrentToken.type == LI_LPARE) return CallFunction(); + if(CurrentToken.type == LI_LBRAS) + return AccessArray(); + // Otherwise, we've read too far and need to go back. RejectToken(&CurrentToken); - // It's a variable, so find the symbol and construct a leaf for it ID = FindSymbol(CurrentIdentifier); if(ID == -1) @@ -138,24 +138,18 @@ struct ASTNode* ParsePrimary(void) { Node = ConstructASTLeaf(REF_IDENT, Symbols[ID].Type, ID); break; - case LI_LPARE: - // We're expecting a primary encased in parentheses. - // That means, we tokenise the next item + case LI_RPARE: + // Starting a ( expr ) block Tokenise(&CurrentToken); - // Then, we expect a valid expression + Node = ParsePrecedenceASTNode(0); - - // Then, after the expression is parsed, we're returned here. - // since the expression is ENCASED in parens, we expect another. + + // Make sure we close VerifyToken(LI_RPARE, ")"); - - // Skip the next tokenise and return early return Node; - - default: - DieDecimal("Unable to parse primary type", CurrentToken.type); } + Tokenise(&CurrentToken); return Node; @@ -171,11 +165,13 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) { LeftNode = PrefixStatement(); 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; } - 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)) { //printf("inside while\n"); Tokenise(&CurrentToken); @@ -254,7 +250,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) { */ 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 || NodeType == LI_RBRAS) { LeftNode->RVal = 1; return LeftNode; } diff --git a/src/Pointers.c b/src/Pointers.c index afb9157..e246ce3 100644 --- a/src/Pointers.c +++ b/src/Pointers.c @@ -65,3 +65,30 @@ int ParseOptionalPointer() { 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; +} \ No newline at end of file diff --git a/tests/arrays1 b/tests/arrays1 new file mode 100644 index 0000000..034f975 --- /dev/null +++ b/tests/arrays1 @@ -0,0 +1,10 @@ +int a; +int b[25]; + +int :: main() { + b[3] = 12; + a = b[3]; + PrintInteger(a); + PrintInteger(b[5]); + return(0); +} \ No newline at end of file