From fcbea5f617edb6e3dfa68eb31efa402b4916c032 Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Mon, 20 Sep 2021 21:47:41 -0700 Subject: Chapter 21.1 - 21.3 --- clox/src/compiler.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 2 deletions(-) (limited to 'clox/src/compiler.c') diff --git a/clox/src/compiler.c b/clox/src/compiler.c index 8606557..9dd7927 100644 --- a/clox/src/compiler.c +++ b/clox/src/compiler.c @@ -88,6 +88,15 @@ static void consume(TokenType type, const char *message) { errorAtCurrent(message); } +static bool check(TokenType type) { return parser.current.type == type; } + +static bool match(TokenType type) { + if (!check(type)) + return false; + advance(); + return true; +} + static void emitByte(uint8_t byte) { writeChunk(currentChunk(), byte, parser.previous.line); } @@ -123,8 +132,12 @@ static void endCompiler() { } static void expression(); +static void statement(); +static void declaration(); static ParseRule *getRule(TokenType type); static void parsePrecedence(Precedence precedence); +static uint8_t parseVariable(const char *name); +static void defineVariable(uint8_t global); static void binary() { TokenType operatorType = parser.previous.type; @@ -185,6 +198,74 @@ static void literal() { static void expression() { parsePrecedence(PREC_ASSIGNMENT); } +static void varDeclaration() { + uint8_t global = parseVariable("Expect variable name."); + + if (match(TOKEN_EQUAL)) { + expression(); + } else { + emitByte(OP_NIL); + } + consume(TOKEN_SEMICOLON, "Expect ';' after variable declaration."); + + defineVariable(global); +} + +static void expressionStatement() { + expression(); + consume(TOKEN_SEMICOLON, "Expect ';' after expression."); + emitByte(OP_POP); +} + +static void printStatement() { + expression(); + consume(TOKEN_SEMICOLON, "Expect ';' after value."); + emitByte(OP_PRINT); +} + +static void synchronize() { + parser.panicMode = false; + + while (parser.current.type != TOKEN_EOF) { + if (parser.previous.type == TOKEN_SEMICOLON) + return; + switch (parser.current.type) { + case TOKEN_CLASS: + case TOKEN_FUN: + case TOKEN_VAR: + case TOKEN_FOR: + case TOKEN_IF: + case TOKEN_WHILE: + case TOKEN_PRINT: + case TOKEN_RETURN: + return; + + default:; /* Do nothing */ + } + } + + advance(); +} + +static void declaration() { + if (match(TOKEN_VAR)) { + varDeclaration(); + } else { + statement(); + } + + if (parser.panicMode) + synchronize(); +} + +static void statement() { + if (match(TOKEN_PRINT)) { + printStatement(); + } else { + expressionStatement(); + } +} + static void number() { double value = strtod(parser.previous.start, NULL); emitConstant(NUMBER_VAL(value)); @@ -279,6 +360,19 @@ static void parsePrecedence(Precedence precedence) { } } +static uint8_t identifierConstant(Token *name) { + return makeConstant(OBJ_VAL(copyString(name->start, name->length))); +} + +static uint8_t parseVariable(const char *errorMessage) { + consume(TOKEN_IDENTIFIER, errorMessage); + return identifierConstant(&parser.previous); +} + +static void defineVariable(uint8_t global) { + emitBytes(OP_DEFINE_GLOBAL, global); +} + static ParseRule *getRule(TokenType type) { return &rules[type]; } bool compile(const char *source, Chunk *chunk) { @@ -289,8 +383,11 @@ bool compile(const char *source, Chunk *chunk) { parser.panicMode = false; advance(); - expression(); - consume(TOKEN_EOF, "Expect end of expression."); + + while (!match(TOKEN_EOF)) { + declaration(); + } + endCompiler(); return !parser.hadError; } -- cgit v1.2.3-54-g00ecf