-
Notifications
You must be signed in to change notification settings - Fork 0
/
lexer.ts
103 lines (92 loc) · 2.33 KB
/
lexer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { Token, TokenTypes, Keywords } from "./token";
type LexerType = {
input: string;
position: number;
readPosition: number;
char: string;
}
export class Lexer {
private position: number = 0;
private readPosition: number = 0;
private char!: string;
private input: string
constructor(input: string) {
this.input = input;
this.readChar();
}
private readChar() {
if (this.readPosition > this.input.length) {
this.char = "\0";
} else {
this.char = this.input[this.readPosition];
}
this.position = this.readPosition;
this.readPosition += 1;
}
nextToken() {
let token: Token | undefined;
switch(this.char) {
case("="): {
token = new Token(TokenTypes.Assign, this.char)
break;
}
case(";"): {
token = new Token(TokenTypes.Semicolon, this.char)
break;
}
case("("): {
token = new Token(TokenTypes.LParen, this.char)
break;
}
case(")"): {
token = new Token(TokenTypes.RParen, this.char)
break;
}
case(","): {
token = new Token(TokenTypes.Comma, this.char)
break;
}
case("+"): {
token = new Token(TokenTypes.Plus, this.char)
break;
}
case("{"): {
token = new Token(TokenTypes.LBrace, this.char)
break;
}
case("}"): {
token = new Token(TokenTypes.RBrace, this.char)
break;
}
case("\0"): {
token = new Token(TokenTypes.Eof, "")
break;
}
default: {
if (this.isLetter(this.char)) {
const identifier = this.readIdentifier()
const keyword = Keywords[identifier as keyof typeof Keywords];
if (keyword) {
return new Token(keyword, identifier);
} else {
return new Token(TokenTypes.Ident, identifier);
}
} else {
token = new Token(TokenTypes.Illegal, this.char);
}
}
}
this.readChar();
return token;
}
readIdentifier():string {
const currentPosition = this.position;
while (this.isLetter(this.char)) {
this.readChar()
}
return this.input.slice(currentPosition, this.position)
}
isLetter(char: string): boolean {
return "a" <= char && char <= "z" || "A" <= char && char <= "Z" || char == "_"
}
}