Skip to content

Commit a7d46ea

Browse files
committed
lexer done: should be extended
1 parent 773b873 commit a7d46ea

File tree

4 files changed

+109
-23
lines changed

4 files changed

+109
-23
lines changed

lexer/lexer.go

+29-1
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,25 @@ func (l *Lexer) readChar() {
2727
l.readPosition += 1
2828
}
2929

30+
func (l *Lexer) readIdentifier() string {
31+
position := l.position
32+
for isLetter(l.ch) {
33+
l.readChar()
34+
}
35+
return l.input[position:l.position]
36+
}
37+
38+
func (l *Lexer) readNumber() string {
39+
position := l.position
40+
for isDigit(l.ch) {
41+
l.readChar()
42+
}
43+
return l.input[position:l.position]
44+
}
45+
3046
func (l *Lexer) NextToken() token.Token {
3147
var tok token.Token
32-
48+
l.skipWhitespace()
3349
switch l.ch {
3450
case '=':
3551
tok = newToken(token.ASSIGN, l.ch)
@@ -50,6 +66,18 @@ func (l *Lexer) NextToken() token.Token {
5066
case 0:
5167
tok.Literal = ""
5268
tok.Type = token.EOF
69+
default:
70+
if isLetter(l.ch) {
71+
tok.Literal = l.readIdentifier()
72+
tok.Type = token.LookupIndent(tok.Literal)
73+
return tok
74+
} else if isDigit(l.ch) {
75+
tok.Type = token.INT
76+
tok.Literal = l.readNumber()
77+
return tok
78+
} else {
79+
tok = newToken(token.ILLEGAL, l.ch)
80+
}
5381
}
5482
l.readChar()
5583
return tok

lexer/lexer_helpers.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package lexer
2+
3+
func isDigit(ch byte) bool {
4+
return '0' <= ch && ch <= '9'
5+
}
6+
7+
func (l *Lexer) skipWhitespace() {
8+
for l.ch == ' ' || l.ch == '\t' || l.ch == '\n' || l.ch == '\r' {
9+
l.readChar()
10+
}
11+
}
12+
func isLetter(ch byte) bool {
13+
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'
14+
}

lexer/lexer_test.go

+36-2
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,53 @@ import (
77
)
88

99
func TestNextToken(t *testing.T) {
10-
input := `=+(){},;`
10+
// input := `=+(){},;`
11+
input := `var five = 5;
12+
var ten = 10;
13+
var add = fn(x, y) {
14+
x + y;
15+
};
16+
var result = add(five, ten);`
1117

1218
tests := []struct {
1319
expectedType token.TokenType
1420
expectedLiteral string
1521
}{
22+
{token.VAR, "var"},
23+
{token.IDENT, "five"},
1624
{token.ASSIGN, "="},
17-
{token.PLUS, "+"},
25+
{token.INT, "5"},
26+
{token.SEMICOLON, ";"},
27+
{token.VAR, "var"},
28+
{token.IDENT, "ten"},
29+
{token.ASSIGN, "="},
30+
{token.INT, "10"},
31+
{token.SEMICOLON, ";"},
32+
{token.VAR, "var"},
33+
{token.IDENT, "add"},
34+
{token.ASSIGN, "="},
35+
{token.FUNCTION, "fn"},
1836
{token.LPAREN, "("},
37+
{token.IDENT, "x"},
38+
{token.COMMA, ","},
39+
{token.IDENT, "y"},
1940
{token.RPAREN, ")"},
2041
{token.LBRACE, "{"},
42+
{token.IDENT, "x"},
43+
{token.PLUS, "+"},
44+
{token.IDENT, "y"},
45+
{token.SEMICOLON, ";"},
2146
{token.RBRACE, "}"},
47+
{token.SEMICOLON, ";"},
48+
{token.VAR, "var"},
49+
{token.IDENT, "result"},
50+
{token.ASSIGN, "="},
51+
{token.IDENT, "add"},
52+
{token.LPAREN, "("},
53+
{token.IDENT, "five"},
2254
{token.COMMA, ","},
55+
{token.IDENT, "ten"},
56+
{token.RPAREN, ")"},
2357
{token.SEMICOLON, ";"},
2458
{token.EOF, ""},
2559
}

token/token.go

+30-20
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,35 @@ type Token struct {
77
Literal string
88
}
99

10+
const (
11+
ILLEGAL = "ILLEGAL"
12+
EOF = "EOF"
13+
// Identifiers + literals
14+
IDENT = "IDENT" // add, foobar, x, y, ...
15+
INT = "INT" // 1343456
16+
// Operators
17+
ASSIGN = "="
18+
PLUS = "+"
19+
// Delimiters
20+
COMMA = ","
21+
SEMICOLON = ";"
22+
LPAREN = "("
23+
RPAREN = ")"
24+
LBRACE = "{"
25+
RBRACE = "}"
26+
// Keywords
27+
FUNCTION = "FUNCTION"
28+
VAR = "VAR"
29+
)
1030

31+
var keywords = map[string]TokenType{
32+
"fn": FUNCTION,
33+
"var": VAR,
34+
}
1135

12-
const (
13-
ILLEGAL = "ILLEGAL"
14-
EOF = "EOF"
15-
// Identifiers + literals
16-
IDENT = "IDENT" // add, foobar, x, y, ...
17-
INT = "INT" // 1343456
18-
// Operators
19-
ASSIGN = "="
20-
PLUS = "+"
21-
// Delimiters
22-
COMMA = ","
23-
SEMICOLON = ";"
24-
LPAREN = "("
25-
RPAREN = ")"
26-
LBRACE = "{"
27-
RBRACE = "}"
28-
// Keywords
29-
FUNCTION = "FUNCTION"
30-
LET = "LET"
31-
)
36+
func LookupIndent(ident string) TokenType {
37+
if tok, ok := keywords[ident]; ok {
38+
return tok
39+
}
40+
return IDENT
41+
}

0 commit comments

Comments
 (0)