From 964859a8a135d890019ee31d0a474b90b9b78b4e Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Tue, 17 Aug 2021 20:41:54 -0700 Subject: Chapter 17.5 - 17.6 --- clox/src/compiler.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 2 deletions(-) (limited to 'clox/src') diff --git a/clox/src/compiler.c b/clox/src/compiler.c index c002ea8..578af94 100644 --- a/clox/src/compiler.c +++ b/clox/src/compiler.c @@ -26,6 +26,14 @@ typedef enum { PREC_PRIMARY } Precedence; +typedef void (*ParseFn)(); + +typedef struct { + ParseFn prefix; + ParseFn infix; + Precedence precedence; +} ParseRule; + Parser parser; Chunk *compilingChunk; @@ -103,9 +111,33 @@ static void emitConstant(Value value) { static void endCompiler() { emitReturn(); } -static void parsePrecedence(Precedence precedence) { - // What goes here? +static void expression(); +static ParseRule *getRule(TokenType type); +static void parsePrecedence(Precedence precedence); + +static void binary() { + TokenType operatorType = parser.previous.type; + ParseRule *rule = getRule(operatorType); + parsePrecedence((Precedence)(rule->precedence + 1)); + + switch (operatorType) { + case TOKEN_PLUS: + emitByte(OP_ADD); + break; + case TOKEN_MINUS: + emitByte(OP_SUBTRACT); + break; + case TOKEN_STAR: + emitByte(OP_MULTIPLY); + break; + case TOKEN_SLASH: + emitByte(OP_DIVIDE); + break; + default: + return; // Unreachable. + } } + static void expression() { parsePrecedence(PREC_ASSIGNMENT); } static void number() { @@ -134,6 +166,68 @@ static void grouping() { consume(TOKEN_RIGHT_PAREN, "Expect ')' after expression."); } +ParseRule rules[] = { + [TOKEN_LEFT_PAREN] = {grouping, NULL, PREC_NONE}, + [TOKEN_RIGHT_PAREN] = {NULL, NULL, PREC_NONE}, + [TOKEN_LEFT_BRACE] = {NULL, NULL, PREC_NONE}, + [TOKEN_RIGHT_BRACE] = {NULL, NULL, PREC_NONE}, + [TOKEN_COMMA] = {NULL, NULL, PREC_NONE}, + [TOKEN_DOT] = {NULL, NULL, PREC_NONE}, + [TOKEN_MINUS] = {unary, binary, PREC_TERM}, + [TOKEN_PLUS] = {NULL, binary, PREC_TERM}, + [TOKEN_SEMICOLON] = {NULL, NULL, PREC_NONE}, + [TOKEN_SLASH] = {NULL, binary, PREC_FACTOR}, + [TOKEN_STAR] = {NULL, binary, PREC_FACTOR}, + [TOKEN_BANG] = {NULL, NULL, PREC_NONE}, + [TOKEN_BANG_EQUAL] = {NULL, NULL, PREC_NONE}, + [TOKEN_EQUAL] = {NULL, NULL, PREC_NONE}, + [TOKEN_EQUAL_EQUAL] = {NULL, NULL, PREC_NONE}, + [TOKEN_GREATER] = {NULL, NULL, PREC_NONE}, + [TOKEN_GREATER_EQUAL] = {NULL, NULL, PREC_NONE}, + [TOKEN_LESS] = {NULL, NULL, PREC_NONE}, + [TOKEN_LESS_EQUAL] = {NULL, NULL, PREC_NONE}, + [TOKEN_IDENTIFIER] = {NULL, NULL, PREC_NONE}, + [TOKEN_STRING] = {NULL, NULL, PREC_NONE}, + [TOKEN_NUMBER] = {number, NULL, PREC_NONE}, + [TOKEN_AND] = {NULL, NULL, PREC_NONE}, + [TOKEN_CLASS] = {NULL, NULL, PREC_NONE}, + [TOKEN_ELSE] = {NULL, NULL, PREC_NONE}, + [TOKEN_FALSE] = {NULL, NULL, PREC_NONE}, + [TOKEN_FOR] = {NULL, NULL, PREC_NONE}, + [TOKEN_FUN] = {NULL, NULL, PREC_NONE}, + [TOKEN_IF] = {NULL, NULL, PREC_NONE}, + [TOKEN_NIL] = {NULL, NULL, PREC_NONE}, + [TOKEN_OR] = {NULL, NULL, PREC_NONE}, + [TOKEN_PRINT] = {NULL, NULL, PREC_NONE}, + [TOKEN_RETURN] = {NULL, NULL, PREC_NONE}, + [TOKEN_SUPER] = {NULL, NULL, PREC_NONE}, + [TOKEN_THIS] = {NULL, NULL, PREC_NONE}, + [TOKEN_TRUE] = {NULL, NULL, PREC_NONE}, + [TOKEN_VAR] = {NULL, NULL, PREC_NONE}, + [TOKEN_WHILE] = {NULL, NULL, PREC_NONE}, + [TOKEN_ERROR] = {NULL, NULL, PREC_NONE}, + [TOKEN_EOF] = {NULL, NULL, PREC_NONE}, +}; + +static void parsePrecedence(Precedence precedence) { + advance(); + ParseFn prefixRule = getRule(parser.previous.type)->prefix; + if (prefixRule == NULL) { + error("Expect expression."); + return; + } + + prefixRule(); + + while (precedence <= getRule(parser.current.type)->precedence) { + advance(); + ParseFn infixRule = getRule(parser.previous.type)->infix; + infixRule(); + } +} + +static ParseRule *getRule(TokenType type) { return &rules[type]; } + bool compile(const char *source, Chunk *chunk) { initScanner(source); compilingChunk = chunk; -- cgit v1.2.3-54-g00ecf