-
Notifications
You must be signed in to change notification settings - Fork 0
/
lexer.odin
96 lines (79 loc) · 1.99 KB
/
lexer.odin
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
package ini
import "core:fmt"
import "core:unicode/utf8"
Lexer :: struct {
tokens: [dynamic]Token,
input: []rune,
pos: int,
line: int,
col: int,
}
new_lexer :: proc(input: string) -> ^Lexer {
l := new(Lexer)
l.tokens = make([dynamic]Token, 0, len(input)/2)
l.input = utf8.string_to_runes(input)
l.pos = 0
l.line = 1
l.col = 0
return l
}
lex :: proc(l: ^Lexer) -> [dynamic]Token {
c: rune
for l.pos < len(l.input) {
switch c = next(l); c {
case '\n': append(&l.tokens, Token{.EOL, "\n", l.line, l.col})
case ';', '#': append(&l.tokens, Token{.COMMENT, lexId(l).value, l.line, l.col})
case ']': append(&l.tokens, Token{.RSB, "]", l.line, l.col})
case '[': append(&l.tokens, Token{.LSB, "[", l.line, l.col})
case '=', ':': append(&l.tokens, Token{.DELIMITER, "=", l.line, l.col})
case ' ', '\t', '\r': break
case: append(&l.tokens, lexId(l))
}
}
append(&l.tokens, Token{.EOF, "", l.line, l.col})
return l.tokens
}
lexId :: proc(l: ^Lexer) -> Token {
start := l.pos - 1
for l.pos < len(l.input) {
c := next(l)
if c == 0 || c == '\n' || c == '[' || c == ']' || c == '=' {
back(l)
break
}
}
return Token{.ID, utf8.runes_to_string(l.input[start:l.pos]), l.line, l.col}
}
lexComment :: proc(l: ^Lexer) -> Token {
start := l.pos - 1
for l.pos < len(l.input) {
c := next(l)
if c == 0 || c == '\n' {
back(l)
break
}
}
return Token{.ID, utf8.runes_to_string(l.input[start:l.pos]), l.line, l.col}
}
back :: proc(l: ^Lexer) {
l.pos -= 1
if l.input[l.pos] == '\n' {
l.line -= 1
} else {
l.col -= 1
}
}
next :: proc(l: ^Lexer) -> rune {
if l.pos >= len(l.input) {
return 0
}
c := l.input[l.pos]
l.pos += 1
if c == '\n' {
l.line += 1
l.col = 1
} else {
l.col += 1
}
return c
}