Skip to content

Commit 5587e80

Browse files
committed
init interpreter
1 parent bafc970 commit 5587e80

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

projects/interpreter/go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module jmelahman/interpreter
2+
3+
go 1.23.0

projects/interpreter/lexer/lexer.go

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package lexer
2+
3+
import "jmelahman/interpreter/token"
4+
5+
type Lexer struct {
6+
input string
7+
position int
8+
readPosition int
9+
ch byte
10+
}
11+
12+
func New(input string) *Lexer {
13+
l := &Lexer{input: input}
14+
l.readChar()
15+
return l
16+
}
17+
18+
func (l *Lexer) readChar() {
19+
if l.readPosition >= len(l.input) {
20+
l.ch = 0
21+
} else {
22+
l.ch = l.input[l.readPosition]
23+
}
24+
l.position = l.readPosition
25+
l.readPosition++
26+
}
27+
28+
func (l *Lexer) NextToken() token.Token {
29+
var tok token.Token
30+
31+
switch l.ch {
32+
case '=':
33+
tok = newToken(token.ASSIGN, l.ch)
34+
case ';':
35+
tok = newToken(token.SEMICOLON, l.ch)
36+
case '(':
37+
tok = newToken(token.LPAREN, l.ch)
38+
case ')':
39+
tok = newToken(token.RPAREN, l.ch)
40+
case ',':
41+
tok = newToken(token.COMMA, l.ch)
42+
case '+':
43+
tok = newToken(token.PLUS, l.ch)
44+
case '{':
45+
tok = newToken(token.LBRACE, l.ch)
46+
case '}':
47+
tok = newToken(token.RBRACE, l.ch)
48+
case 0:
49+
tok.Literal = ""
50+
tok.Type = token.EOF
51+
}
52+
53+
l.readChar()
54+
return tok
55+
}
56+
57+
func newToken(tokenType token.TokenType, ch byte) token.Token {
58+
return token.Token{Type: tokenType, Literal: string(ch)}
59+
}
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package lexer
2+
3+
import (
4+
"jmelahman/interpreter/token"
5+
"testing"
6+
)
7+
8+
func TestNextToken(t *testing.T) {
9+
input := `=+(){},;`
10+
11+
tests := []struct {
12+
expectedType token.TokenType
13+
expectedLiteral string
14+
}{
15+
{token.ASSIGN, "="},
16+
{token.PLUS, "+"},
17+
{token.LPAREN, "("},
18+
{token.RPAREN, ")"},
19+
{token.LBRACE, "{"},
20+
{token.RBRACE, "}"},
21+
{token.COMMA, ","},
22+
{token.SEMICOLON, ";"},
23+
{token.EOF, ""},
24+
}
25+
26+
l := New(input)
27+
28+
for i, tt := range tests {
29+
tok := l.NextToken()
30+
31+
if tok.Type != tt.expectedType {
32+
t.Fatalf("tests[%d] - tokentype wrong. expected=%q, got=%q", i, tt.expectedType, tok.Type)
33+
}
34+
if tok.Literal != tt.expectedLiteral {
35+
t.Fatalf("tests[%d] - literal wrong. expected=%q, got=%q", i, tt.expectedLiteral, tok.Literal)
36+
}
37+
}
38+
}

projects/interpreter/token/token.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package token
2+
3+
type TokenType string
4+
5+
type Token struct {
6+
Type TokenType
7+
Literal string
8+
}
9+
10+
const (
11+
ILLEGAL = "ILLEGAL"
12+
EOF = "EOF"
13+
14+
// Identifiers + literals
15+
IDENT = "IDENT"
16+
INT = "INT"
17+
18+
// Operators
19+
ASSIGN = "="
20+
PLUS = "+"
21+
22+
// Delimiters
23+
COMMA = ","
24+
SEMICOLON = ";"
25+
26+
LPAREN = "("
27+
RPAREN = ")"
28+
LBRACE = "{"
29+
RBRACE = "}"
30+
31+
// Keywords
32+
FUNCTION = "FUNCTION"
33+
LET = "LET"
34+
)

0 commit comments

Comments
 (0)