Skip to content

Commit 325643c

Browse files
committed
lang: add basic token and lexer support
1 parent edbab29 commit 325643c

File tree

2 files changed

+126
-0
lines changed

2 files changed

+126
-0
lines changed

internal/lexer/lexer.go

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package lexer
2+
3+
import (
4+
"github.com/nsecho/gxpc/internal/token"
5+
"unicode"
6+
)
7+
8+
func New(input string) *Lexer {
9+
l := &Lexer{input: input}
10+
l.readChar()
11+
return l
12+
}
13+
14+
type Lexer struct {
15+
input string
16+
position int
17+
readPosition int
18+
ch byte
19+
}
20+
21+
func (l *Lexer) NextToken() token.Token {
22+
var tok token.Token
23+
l.skipWhitespace()
24+
25+
switch l.ch {
26+
case '=':
27+
if l.peekChar() == '>' {
28+
l.readChar()
29+
tok.Literal = "=>"
30+
tok.TokenType = token.DEF
31+
} else {
32+
tok = newToken(token.EQ, l.ch)
33+
}
34+
case '>':
35+
tok = newToken(token.GT, l.ch)
36+
case 0:
37+
tok = newToken(token.EOF, 0)
38+
default:
39+
if unicode.IsLetter(rune(l.ch)) {
40+
tok.Literal = l.readIdentifier()
41+
tok.TokenType = token.LookupIdent(tok.Literal)
42+
return tok
43+
} else {
44+
tok = newToken(token.ILLEGAL, l.ch)
45+
}
46+
}
47+
48+
l.readChar()
49+
return tok
50+
}
51+
52+
func (l *Lexer) readIdentifier() string {
53+
pos := l.position
54+
for unicode.IsLetter(rune(l.ch)) || l.ch == '_' {
55+
l.readChar()
56+
}
57+
return l.input[pos:l.position]
58+
}
59+
60+
func (l *Lexer) readChar() {
61+
if l.readPosition >= len(l.input) {
62+
l.ch = 0
63+
} else {
64+
l.ch = l.input[l.readPosition]
65+
}
66+
l.position = l.readPosition
67+
l.readPosition += 1
68+
}
69+
70+
func (l *Lexer) skipWhitespace() {
71+
for unicode.IsSpace(rune(l.ch)) {
72+
l.readChar()
73+
}
74+
}
75+
76+
func (l *Lexer) atEOF() bool {
77+
return l.readPosition >= len(l.input)
78+
}
79+
80+
func (l *Lexer) peekChar() byte {
81+
if l.atEOF() {
82+
return 0
83+
}
84+
85+
return l.input[l.readPosition]
86+
}
87+
88+
func newToken(t token.Type, literal byte) token.Token {
89+
return token.Token{
90+
TokenType: t,
91+
Literal: string(literal),
92+
}
93+
}

internal/token/token.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package token
2+
3+
type Type string
4+
5+
const (
6+
ILLEGAL Type = "ILLEGAL"
7+
EOF = "EOF"
8+
9+
IDENT = "IDENT"
10+
11+
EQ = "="
12+
GT = ">"
13+
14+
DEF = "=>"
15+
16+
FN = "FN"
17+
)
18+
19+
var keywords = map[string]Type{
20+
"fn": FN,
21+
}
22+
23+
func LookupIdent(ident string) Type {
24+
if tok, ok := keywords[ident]; ok {
25+
return tok
26+
}
27+
return IDENT
28+
}
29+
30+
type Token struct {
31+
TokenType Type
32+
Literal string
33+
}

0 commit comments

Comments
 (0)