From 41a04094e296f437f2b379595013d22e96e05054 Mon Sep 17 00:00:00 2001 From: Garritt McCune Date: Mon, 28 Feb 2022 20:13:59 +0000 Subject: [PATCH] Added untested parser code, meaning most of chapter 6 has been implemented (but most likely, very poorly). --- .gitignore | 1 + build.sh | 1 + expr.c | 6 ++ expr.h | 21 +++--- parser.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++ parser.h | 6 ++ 6 files changed, 217 insertions(+), 8 deletions(-) create mode 100755 build.sh create mode 100644 expr.c create mode 100644 parser.c create mode 100644 parser.h diff --git a/.gitignore b/.gitignore index e48d01a..eb84848 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ clox +*.lox diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..1a1f8a8 --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +gcc -o clox lox.c scanner.c parser.c diff --git a/expr.c b/expr.c new file mode 100644 index 0000000..ac33163 --- /dev/null +++ b/expr.c @@ -0,0 +1,6 @@ +#include "expr.h" + +void VisitBinary(struct binary); +void VisitGrouping(struct grouping); +void VisitLiteral(struct literal); +void VisitUnary(struct unary); \ No newline at end of file diff --git a/expr.h b/expr.h index 283e900..eee6a95 100644 --- a/expr.h +++ b/expr.h @@ -12,26 +12,26 @@ typedef enum { OPERATOR } ExpressionType; -typedef struct Expr expression; +typedef struct Expr Expr; struct binary { - Expr* left; - TokenType op; - Expr* right; + struct Expr* left; + Token* op; + struct Expr* right; }; struct grouping { - Expr* expression; + struct Expr* expression; }; struct literal { - TokenType type; //Probably something to this effect. + Token* type; void* object; }; struct unary { - TokenType op; - Expr* right; + Token* op; + struct Expr* right; }; struct Expr { @@ -44,4 +44,9 @@ struct Expr { } expression; }; +void VisitBinary(struct binary); +void VisitGrouping(struct grouping); +void VisitLiteral(struct literal); +void VisitUnary(struct unary); + #endif \ No newline at end of file diff --git a/parser.c b/parser.c new file mode 100644 index 0000000..6a45487 --- /dev/null +++ b/parser.c @@ -0,0 +1,190 @@ +#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; +} \ No newline at end of file diff --git a/parser.h b/parser.h new file mode 100644 index 0000000..85c1117 --- /dev/null +++ b/parser.h @@ -0,0 +1,6 @@ +#ifndef PARSER_H +#define PARSER_H + + + +#endif \ No newline at end of file