-
Notifications
You must be signed in to change notification settings - Fork 0
/
lex.go
85 lines (74 loc) · 1.17 KB
/
lex.go
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
package bit
import (
"errors"
"fmt"
"io"
)
type lex struct {
r io.Reader
read []byte
buf [4096]byte
line int
col int
off int
prog *Program
}
func (l *lex) Lex(lval *yySymType) int {
for {
for len(l.read) == 0 {
n, err := l.r.Read(l.buf[:])
if err != nil {
if err == io.EOF {
return 0
}
panic(err)
}
l.read = l.buf[:n]
}
var b byte
b, l.read = l.read[0], l.read[1:]
l.off++
l.col++
if b == '\n' {
l.col = 0
l.line++
continue
}
if b == ' ' || b == '\t' {
continue
}
return int(b)
}
}
func (l *lex) Error(s string) {
panic(errors.New(s))
}
type ParseError struct {
Err error
Line int
Column int
Offset int
}
func (err *ParseError) Error() string {
return fmt.Sprintf("bit: on line %d column %d (offset %d): %v", err.Line, err.Column, err.Offset, err.Err)
}
func Parse(r io.Reader) (prog Program, err error) {
l := &lex{r: r, line: 1}
defer func() {
if r := recover(); r != nil {
err = r.(error)
err = &ParseError{
Err: err,
Line: l.line,
Column: l.col,
Offset: l.off,
}
}
}()
yyParse(l)
err = l.prog.Init()
if err != nil {
return
}
return *l.prog, nil
}