#include "parser.h" #include "expr.h" #include "scanner.h" #include #include #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 IsAtEnd(void); Token* Peek(void); Token* Previous(void); Token* Advance(void); Token* CreateToken(char*, TokenType); const TokenList* tokens; int Current = 0; //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(1, FALSE)) { expr->expression.Literal.type = CreateToken("false", FALSE); return expr; } if (Match(1, TRUE)) { expr->expression.Literal.type = CreateToken("true", TRUE); return expr; } if (Match(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(); //Consume(RParen, "Expect ')' after expression."); expr->type = GROUPING; return expr; } return expr; } int Match(int count, ...) { va_list list; va_start(list, count); for(int i = 0; i < count; i++) { if(Check(va_arg(list, TokenType))) { Advance(); return 1; } } return 0; } int Check(TokenType type) { if (IsAtEnd()) return 0; return Peek()->type == type; } int IsAtEnd() { return Peek()->type == EndOF; } Token* Peek() { return tokens->tokens[Current]; } Token* Previous() { return tokens->tokens[Current - 1]; } Token* Advance() { if (!IsAtEnd()) Current++; return Previous(); } Token* CreateToken(char* lexeme, TokenType type) { Token* token = calloc(1, sizeof(Token)); token->type = type; token->lexeme = lexeme; token->length = strlen(lexeme); return token; }