From 350a5cc4e3e6c19c2e01d9150b147b696dd13aea Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Sat, 7 Aug 2021 21:23:05 -0700 Subject: [PATCH] Chapter 16.4 --- clox/src/scanner.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/clox/src/scanner.c b/clox/src/scanner.c index 15d6484..5e0f4bf 100644 --- a/clox/src/scanner.c +++ b/clox/src/scanner.c @@ -18,6 +18,10 @@ void initScanner(const char *source) { scanner.line = 1; } +static bool isAlpha(char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; +} + static bool isDigit(char c) { return c >= '0' && c <= '9'; } static bool isAtEnd() { return *scanner.current == '\0'; } @@ -91,6 +95,73 @@ static void skipWhitespace() { } } +static TokenType checkKeyword(int start, int length, const char *rest, + TokenType type) { + if (scanner.current - scanner.start == start + length && + memcmp(scanner.start + start, rest, length) == 0) { + return type; + } + + return TOKEN_IDENTIFIER; +} + +static TokenType identifierType() { + switch (scanner.start[0]) { + case 'a': + return checkKeyword(1, 2, "nd", TOKEN_AND); + case 'c': + return checkKeyword(1, 4, "lass", TOKEN_CLASS); + case 'e': + return checkKeyword(1, 3, "lse", TOKEN_ELSE); + case 'f': + if (scanner.current - scanner.start > 1) { + switch (scanner.start[1]) { + case 'a': + return checkKeyword(2, 3, "lse", TOKEN_FALSE); + case 'o': + return checkKeyword(2, 1, "or", TOKEN_FOR); + case 'u': + return checkKeyword(2, 1, "n", TOKEN_FUN); + } + } + break; + case 'i': + return checkKeyword(1, 1, "f", TOKEN_IF); + case 'n': + return checkKeyword(1, 2, "il", TOKEN_NIL); + case 'o': + return checkKeyword(1, 1, "r", TOKEN_OR); + case 'p': + return checkKeyword(1, 4, "rint", TOKEN_PRINT); + case 'r': + return checkKeyword(1, 5, "eturn", TOKEN_RETURN); + case 's': + return checkKeyword(1, 4, "uper", TOKEN_SUPER); + case 't': + if (scanner.current - scanner.start > 1) { + switch (scanner.start[1]) { + case 'h': + return checkKeyword(2, 2, "is", TOKEN_THIS); + case 'r': + return checkKeyword(2, 2, "ue", TOKEN_TRUE); + } + } + break; + case 'v': + return checkKeyword(1, 2, "ar", TOKEN_VAR); + case 'w': + return checkKeyword(1, 4, "hile", TOKEN_WHILE); + } + + return TOKEN_IDENTIFIER; +} + +static Token identifier() { + while (isAlpha(peek()) || isDigit(peek())) + advance(); + return makeToken(identifierType()); +} + static Token number() { while (isDigit(peek())) advance(); @@ -130,6 +201,9 @@ Token scanToken() { return makeToken(TOKEN_EOF); char c = advance(); + + if (isAlpha(c)) + return identifier(); if (isDigit(c)) return number();