Chapter 16.3
This commit is contained in:
parent
4143259eb3
commit
eb6f33a2b2
1 changed files with 124 additions and 0 deletions
|
@ -18,8 +18,32 @@ void initScanner(const char *source) {
|
||||||
scanner.line = 1;
|
scanner.line = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isDigit(char c) { return c >= '0' && c <= '9'; }
|
||||||
|
|
||||||
static bool isAtEnd() { return *scanner.current == '\0'; }
|
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) {
|
static Token makeToken(TokenType type) {
|
||||||
Token token;
|
Token token;
|
||||||
token.type = type;
|
token.type = type;
|
||||||
|
@ -38,11 +62,111 @@ static Token errorToken(const char *message) {
|
||||||
return token;
|
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() {
|
Token scanToken() {
|
||||||
|
skipWhitespace();
|
||||||
scanner.start = scanner.current;
|
scanner.start = scanner.current;
|
||||||
|
|
||||||
if (isAtEnd())
|
if (isAtEnd())
|
||||||
return makeToken(TOKEN_EOF);
|
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.");
|
return errorToken("Unexpected character.");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue