...
1 package gval
2
3 import (
4 "bytes"
5 "fmt"
6 "strings"
7 "text/scanner"
8 "unicode"
9 )
10
11
12 type Parser struct {
13 scanner scanner.Scanner
14 Language
15 lastScan rune
16 camouflage error
17 }
18
19 func newParser(expression string, l Language) *Parser {
20 sc := scanner.Scanner{}
21 sc.Init(strings.NewReader(expression))
22 sc.Error = func(*scanner.Scanner, string) {}
23 sc.Filename = expression + "\t"
24 p := &Parser{scanner: sc, Language: l}
25 p.resetScannerProperties()
26 return p
27 }
28
29 func (p *Parser) resetScannerProperties() {
30 p.scanner.Whitespace = scanner.GoWhitespace
31 p.scanner.Mode = scanner.GoTokens
32 p.scanner.IsIdentRune = func(r rune, pos int) bool {
33 return unicode.IsLetter(r) || r == '_' || (pos > 0 && unicode.IsDigit(r))
34 }
35 }
36
37
38
39 func (p *Parser) SetWhitespace(chars ...rune) {
40 var mask uint64
41 for _, char := range chars {
42 mask |= 1 << char
43 }
44
45 p.scanner.Whitespace = mask
46 }
47
48
49 func (p *Parser) SetMode(mode uint) {
50 p.scanner.Mode = mode
51 }
52
53
54
55 func (p *Parser) SetIsIdentRuneFunc(fn func(ch rune, i int) bool) {
56 p.scanner.IsIdentRune = fn
57 }
58
59
60
61
62 func (p *Parser) Scan() rune {
63 if p.isCamouflaged() {
64 p.camouflage = nil
65 return p.lastScan
66 }
67 p.camouflage = nil
68 p.lastScan = p.scanner.Scan()
69 return p.lastScan
70 }
71
72 func (p *Parser) isCamouflaged() bool {
73 return p.camouflage != nil && p.camouflage != errCamouflageAfterNext
74 }
75
76
77
78
79 func (p *Parser) Camouflage(unit string, expected ...rune) {
80 if p.isCamouflaged() {
81 panic(fmt.Errorf("can only Camouflage() after Scan(): %w", p.camouflage))
82 }
83 p.camouflage = p.Expected(unit, expected...)
84 }
85
86
87
88
89
90 func (p *Parser) Peek() rune {
91 if p.isCamouflaged() {
92 panic("can not Peek() on camouflaged Parser")
93 }
94 return p.scanner.Peek()
95 }
96
97 var errCamouflageAfterNext = fmt.Errorf("Camouflage() after Next()")
98
99
100
101
102 func (p *Parser) Next() rune {
103 if p.isCamouflaged() {
104 panic("can not Next() on camouflaged Parser")
105 }
106 p.camouflage = errCamouflageAfterNext
107 return p.scanner.Next()
108 }
109
110
111
112 func (p *Parser) TokenText() string {
113 return p.scanner.TokenText()
114 }
115
116
117 func (p *Parser) Expected(unit string, expected ...rune) error {
118 return unexpectedRune{unit, expected, p.lastScan}
119 }
120
121 type unexpectedRune struct {
122 unit string
123 expected []rune
124 got rune
125 }
126
127 func (err unexpectedRune) Error() string {
128 exp := bytes.Buffer{}
129 runes := err.expected
130 switch len(runes) {
131 default:
132 for _, r := range runes[:len(runes)-2] {
133 exp.WriteString(scanner.TokenString(r))
134 exp.WriteString(", ")
135 }
136 fallthrough
137 case 2:
138 exp.WriteString(scanner.TokenString(runes[len(runes)-2]))
139 exp.WriteString(" or ")
140 fallthrough
141 case 1:
142 exp.WriteString(scanner.TokenString(runes[len(runes)-1]))
143 case 0:
144 return fmt.Sprintf("unexpected %s while scanning %s", scanner.TokenString(err.got), err.unit)
145 }
146 return fmt.Sprintf("unexpected %s while scanning %s expected %s", scanner.TokenString(err.got), err.unit, exp.String())
147 }
148
View as plain text