aboutsummaryrefslogtreecommitdiffstats
path: root/clox
diff options
context:
space:
mode:
authorGravatar Tom Willemse2021-08-07 21:23:05 -0700
committerGravatar Tom Willemse2021-08-07 21:23:05 -0700
commit350a5cc4e3e6c19c2e01d9150b147b696dd13aea (patch)
tree4e6301ecba52f54a2a92703d599d623165969f45 /clox
parenteb6f33a2b2ffb63f746d543f55f961ce06ee73b7 (diff)
downloadcrafting-interpreters-350a5cc4e3e6c19c2e01d9150b147b696dd13aea.tar.gz
crafting-interpreters-350a5cc4e3e6c19c2e01d9150b147b696dd13aea.zip
Chapter 16.4
Diffstat (limited to 'clox')
-rw-r--r--clox/src/scanner.c74
1 files changed, 74 insertions, 0 deletions
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();