#include "parser.h" #include "expr.h" #include Expr* Expression(void); Expr* Equality(void); Expr* Comparison(void); Expr* Term(void); Expr* Factor(void); Expr* Unary(void); Expr* Primary(void); int Match(int, ...); int Check(TokenType); int ParserAtEnd(void); Token* ParserPeek(void); Token* Previous(void); Token* AdvanceParser(void); const TokenList* ListOfTokens; int Current = 0; Expr* GenerateExpressionTree(const TokenList* list) { ListOfTokens = list; return Expression(); } //Simply expands the equality rule Expr* Expression() { return Equality(); } Expr* Equality() { Expr* expr = Comparison(); while(Match(2, Bang_Equal, Equal_Equal)) { Token* operator = Previous(); Expr* right = Comparison(); Expr* temp = calloc(1, sizeof(Expr)); temp->type = BINARY; temp->expression.Binary.left = expr; temp->expression.Binary.op = operator; temp->expression.Binary.right = right; expr = temp; } return expr; } Expr* Comparison() { Expr* expr = Term(); while(Match(4, Greater, Greater_Equal, Less, Less_Equal)) { Token* operator = Previous(); Expr* right = Term(); Expr* temp = calloc(1, sizeof(Expr)); temp->type = BINARY; temp->expression.Binary.left = expr; temp->expression.Binary.op = operator; temp->expression.Binary.right = right; expr = temp; } return expr; } Expr* Term() { Expr* expr = Factor(); while(Match(2, Minus, Plus)) { Token* operator = Previous(); Expr* right = Factor(); Expr* temp = calloc(1, sizeof(Expr)); temp->type = BINARY; temp->expression.Binary.left = expr; temp->expression.Binary.op = operator; temp->expression.Binary.right = right; expr = temp; } return expr; } Expr* Factor() { Expr* expr = Unary(); while(Match(2, Slash, Star)) { Token* operator = Previous(); Expr* right = Unary(); Expr* temp = calloc(1, sizeof(Expr)); temp->type = BINARY; temp->expression.Binary.left = expr; temp->expression.Binary.op = operator; temp->expression.Binary.right = right; expr = temp; } return expr; } Expr* Unary() { if (Match(2, Bang, Minus)) { Token* operator = Previous(); Expr* right = Unary(); Expr* expr = calloc(1, sizeof(Expr)); expr->type = UNARY; expr->expression.Unary.op = operator; expr->expression.Unary.right = right; return expr; } return Primary(); } Expr* Primary() { Expr* expr = calloc(1, sizeof(Expr)); expr->type = LITERAL; if (Match(3, FALSE, TRUE, NIL)) { expr->expression.Literal.type = ParserPeek();//CreateToken("false", FALSE); return expr; } // if (SMatch(1, TRUE)) { // expr->expression.Literal.type = //CreateToken("true", TRUE); // return expr; // } // if (SMatch(1, NIL)) { // expr->expression.Literal.type = //CreateToken("nil", NIL); // return expr; // } if (Match(2, Number, String)) { expr->expression.Literal.type = Previous(); return expr; } if (Match(1, LParen)) { free(expr); expr = Expression(); Expr* temp = calloc(1, sizeof(Expr)); if (!Check(RParen)) printf("Unbalanced\n"); //Todo: something or another... //Consume(RParen, "Expect ')' after expression."); temp->type = GROUPING; temp->expression.Grouping.expression = expr; return temp; } free(expr); printf("Failed to match Primary\n"); return NULL; } int Match(int count, ...) { va_list list; va_start(list, count); for(int i = 0; i < count; i++) { if(Check(va_arg(list, TokenType))) { AdvanceParser(); return 1; } } return 0; } int Check(TokenType type) { if (ParserAtEnd()) return 0; return ParserPeek()->type == type; } int ParserAtEnd() { return ParserPeek()->type == EndOF; } Token* ParserPeek() { return ListOfTokens->tokens[Current]; } Token* Previous() { return ListOfTokens->tokens[Current - 1]; } Token* AdvanceParser() { if (!ParserAtEnd()) Current++; return Previous(); } void PrintExpressionTree(const Expr* tree) { if (!tree) return; if (tree->type == BINARY) { printf("("); PrintExpressionTree(tree->expression.Binary.left); PrintExpressionTree(tree->expression.Binary.right); printf("%s", tree->expression.Binary.op->lexeme); printf(")"); } else if (tree->type == UNARY) { printf("("); printf("%s", tree->expression.Unary.op->lexeme); PrintExpressionTree(tree->expression.Unary.right); printf(")"); } else if (tree->type == GROUPING) { PrintExpressionTree(tree->expression.Grouping.expression); } else if (tree->type == LITERAL) printf("%s", tree->expression.Literal.type->lexeme); } void FreeExpressionTree(Expr* tree) { if (!tree) return; if (tree->type == BINARY) { FreeExpressionTree(tree->expression.Binary.left); FreeExpressionTree(tree->expression.Binary.right); } else if (tree->type == UNARY) { FreeExpressionTree(tree->expression.Unary.right); } free(tree); }