restructure
This commit is contained in:
parent
b466717c6e
commit
2de4381fae
6 changed files with 26 additions and 10 deletions
147
src/scanner.d
147
src/scanner.d
|
|
@ -1,147 +0,0 @@
|
|||
import std.ascii;
|
||||
import std.conv;
|
||||
|
||||
import token;
|
||||
import tokentype;
|
||||
import main : error, report;
|
||||
|
||||
private bool isAlpha_(dchar c) => c.isAlpha || c == '_';
|
||||
private bool isAlphaNum_(dchar c) => c.isAlphaNum || c == '_';
|
||||
|
||||
class Scanner {
|
||||
private string source;
|
||||
private Token[] tokens;
|
||||
private uint start = 0;
|
||||
private uint current = 0;
|
||||
private uint line = 1;
|
||||
|
||||
this(string source){
|
||||
this.source = source;
|
||||
}
|
||||
private bool isAtEnd(uint n = 0) const => current + n >= source.length;
|
||||
private char advance() => source[current++];
|
||||
private char peek(uint n = 0) const => isAtEnd(n) ? '\0' : source[current + n];
|
||||
private char peekNext() const => peek(1);
|
||||
private bool match(char expected){
|
||||
if(peek() != expected)
|
||||
return false;
|
||||
current++;
|
||||
return true;
|
||||
}
|
||||
private void addToken(TokenType type, TTokenValue literal = TTokenValue.nil(0)){
|
||||
string text = source[start .. current];
|
||||
tokens ~= new Token(type, text, literal, line);
|
||||
}
|
||||
Token[] scanTokens(){
|
||||
while(!isAtEnd){
|
||||
start = current;
|
||||
scanToken();
|
||||
}
|
||||
addToken(TokenType.EOF);
|
||||
return tokens;
|
||||
}
|
||||
private void stringLiteral(){
|
||||
while(peek() != '"' && !isAtEnd){
|
||||
if(peek() == '\n')
|
||||
line++;
|
||||
advance();
|
||||
}
|
||||
if(isAtEnd){
|
||||
error(line, "Unterminated string.");
|
||||
return;
|
||||
}
|
||||
advance();
|
||||
string value = source[start + 1 .. current -1];
|
||||
addToken(TokenType.STRING, TTokenValue.str(value));
|
||||
}
|
||||
private void number(){
|
||||
while(peek().isDigit)
|
||||
advance();
|
||||
if(peek() == '.' && peekNext().isDigit){
|
||||
advance(); // Eat the .
|
||||
while(peek().isDigit)
|
||||
advance();
|
||||
}
|
||||
addToken(TokenType.NUMBER, TTokenValue.dbl(source[start .. current].to!double));
|
||||
}
|
||||
private TokenType keywords(string word){
|
||||
with(TokenType) switch(word){
|
||||
case "and": return AND;
|
||||
case "class": return CLASS;
|
||||
case "else": return ELSE;
|
||||
case "false": return FALSE;
|
||||
case ":or": return FOR;
|
||||
case "fun": return FUN;
|
||||
case "if": return IF;
|
||||
case "nil": return NIL;
|
||||
case "or": return OR;
|
||||
case "print": return PRINT;
|
||||
case "return": return RETURN;
|
||||
case "super": return SUPER;
|
||||
case "this": return THIS;
|
||||
case "true": return TRUE;
|
||||
case "var": return VAR;
|
||||
case "while": return WHILE;
|
||||
default: return IDENTIFIER;
|
||||
}
|
||||
}
|
||||
private void identifier(){
|
||||
while(peek().isAlphaNum_)
|
||||
advance();
|
||||
addToken(keywords(source[start .. current]));
|
||||
}
|
||||
private void scanToken() {
|
||||
char c = advance();
|
||||
with(TokenType) switch(c){
|
||||
case '(': addToken(LEFT_PAREN); break;
|
||||
case ')': addToken(RIGHT_PAREN); break;
|
||||
case '{': addToken(LEFT_BRACE); break;
|
||||
case '}': addToken(RIGHT_BRACE); break;
|
||||
case ',': addToken(COMMA); break;
|
||||
case '.': addToken(DOT); break;
|
||||
case '-': addToken(MINUS); break;
|
||||
case '+': addToken(PLUS); break;
|
||||
case ';': addToken(SEMICOLON); break;
|
||||
case '*': addToken(STAR); break;
|
||||
case '!':
|
||||
addToken(match('=') ? BANG_EQUAL : BANG);
|
||||
break;
|
||||
case '=':
|
||||
addToken(match('=') ? EQUAL_EQUAL : EQUAL);
|
||||
break;
|
||||
case '<':
|
||||
addToken(match('=') ? LESS_EQUAL : LESS);
|
||||
break;
|
||||
case '>':
|
||||
addToken(match('=') ? GREATER_EQUAL : GREATER);
|
||||
break;
|
||||
case '/':
|
||||
if(match('/')){
|
||||
while(peek() != '\n' && !isAtEnd)
|
||||
advance();
|
||||
} else {
|
||||
addToken(SLASH);
|
||||
}
|
||||
break;
|
||||
case ' ', '\r', '\t':
|
||||
break;
|
||||
case '\n':
|
||||
line++;
|
||||
break;
|
||||
case '"':
|
||||
stringLiteral();
|
||||
break;
|
||||
case '0': .. case '9':
|
||||
number();
|
||||
break;
|
||||
case 'a': .. case 'z':
|
||||
case 'A': .. case 'Z':
|
||||
case '_':
|
||||
identifier();
|
||||
break;
|
||||
default:
|
||||
error(line, "Unexpected character");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue