Chapter 16.3

This commit is contained in:
Tom Willemse 2021-08-02 20:44:52 -07:00
parent 4143259eb3
commit eb6f33a2b2
Signed by: ryuslash
GPG key ID: 7D5C407B435025C1

View file

@ -18,8 +18,32 @@ void initScanner(const char *source) {
scanner.line = 1;
}
static bool isDigit(char c) { return c >= '0' && c <= '9'; }
static bool isAtEnd() { return *scanner.current == '\0'; }
static char advance() {
scanner.current++;
return scanner.current[-1];
}
static char peek() { return *scanner.current; }
static char peekNext() {
if (isAtEnd())
return '\0';
return scanner.current[1];
}
static bool match(char expected) {
if (isAtEnd())
return false;
if (*scanner.current != expected)
return false;
scanner.current++;
return true;
}
static Token makeToken(TokenType type) {
Token token;
token.type = type;
@ -38,11 +62,111 @@ static Token errorToken(const char *message) {
return token;
}
static void skipWhitespace() {
for (;;) {
char c = peek();
switch (c) {
case ' ':
case '\r':
case '\t':
advance();
break;
case '\n':
scanner.line++;
advance();
break;
case '/':
if (peekNext() == '/') {
// A comment goes until the end of the line.
while (peek() != '\n' && !isAtEnd())
advance();
} else {
return;
}
break;
default:
return;
}
}
}
static Token number() {
while (isDigit(peek()))
advance();
// Look for a fractional part.
if (peek() == '.' && isDigit(peekNext())) {
// Consume the ".";
advance();
while (isDigit(peek()))
advance();
}
return makeToken(TOKEN_NUMBER);
}
static Token string() {
while (peek() != '"' && !isAtEnd()) {
if (peek() == '\n')
scanner.line++;
advance();
}
if (isAtEnd())
return errorToken("Unterminated string.");
// The closing quote.
advance();
return makeToken(TOKEN_STRING);
}
Token scanToken() {
skipWhitespace();
scanner.start = scanner.current;
if (isAtEnd())
return makeToken(TOKEN_EOF);
char c = advance();
if (isDigit(c))
return number();
switch (c) {
case '(':
return makeToken(TOKEN_LEFT_PAREN);
case ')':
return makeToken(TOKEN_RIGHT_PAREN);
case '{':
return makeToken(TOKEN_LEFT_BRACE);
case '}':
return makeToken(TOKEN_RIGHT_BRACE);
case ';':
return makeToken(TOKEN_SEMICOLON);
case ',':
return makeToken(TOKEN_COMMA);
case '.':
return makeToken(TOKEN_DOT);
case '-':
return makeToken(TOKEN_MINUS);
case '+':
return makeToken(TOKEN_PLUS);
case '/':
return makeToken(TOKEN_SLASH);
case '*':
return makeToken(TOKEN_STAR);
case '!':
return makeToken(match('=') ? TOKEN_BANG_EQUAL : TOKEN_BANG);
case '=':
return makeToken(match('=') ? TOKEN_EQUAL_EQUAL : TOKEN_EQUAL);
case '<':
return makeToken(match('=') ? TOKEN_LESS_EQUAL : TOKEN_LESS);
case '>':
return makeToken(match('=') ? TOKEN_GREATER_EQUAL : TOKEN_GREATER);
case '"':
return string();
}
return errorToken("Unexpected character.");
}