1 package gval
2
3 import (
4 "context"
5 "fmt"
6 "text/scanner"
7 "unicode"
8
9 "github.com/shopspring/decimal"
10 )
11
12
13 type Language struct {
14 prefixes map[interface{}]extension
15 operators map[string]operator
16 operatorSymbols map[rune]struct{}
17 init extension
18 def extension
19 selector func(Evaluables) Evaluable
20 }
21
22
23 func NewLanguage(bases ...Language) Language {
24 l := newLanguage()
25 for _, base := range bases {
26 for i, e := range base.prefixes {
27 l.prefixes[i] = e
28 }
29 for i, e := range base.operators {
30 l.operators[i] = e.merge(l.operators[i])
31 l.operators[i].initiate(i)
32 }
33 for i := range base.operatorSymbols {
34 l.operatorSymbols[i] = struct{}{}
35 }
36 if base.init != nil {
37 l.init = base.init
38 }
39 if base.def != nil {
40 l.def = base.def
41 }
42 if base.selector != nil {
43 l.selector = base.selector
44 }
45 }
46 return l
47 }
48
49 func newLanguage() Language {
50 return Language{
51 prefixes: map[interface{}]extension{},
52 operators: map[string]operator{},
53 operatorSymbols: map[rune]struct{}{},
54 }
55 }
56
57
58 func (l Language) NewEvaluable(expression string) (Evaluable, error) {
59 return l.NewEvaluableWithContext(context.Background(), expression)
60 }
61
62
63 func (l Language) NewEvaluableWithContext(c context.Context, expression string) (Evaluable, error) {
64 p := newParser(expression, l)
65
66 eval, err := p.parse(c)
67 if err == nil && p.isCamouflaged() && p.lastScan != scanner.EOF {
68 err = p.camouflage
69 }
70 if err != nil {
71 pos := p.scanner.Pos()
72 return nil, fmt.Errorf("parsing error: %s - %d:%d %w", p.scanner.Position, pos.Line, pos.Column, err)
73 }
74
75 return eval, nil
76 }
77
78
79 func (l Language) Evaluate(expression string, parameter interface{}) (interface{}, error) {
80 return l.EvaluateWithContext(context.Background(), expression, parameter)
81 }
82
83
84 func (l Language) EvaluateWithContext(c context.Context, expression string, parameter interface{}) (interface{}, error) {
85 eval, err := l.NewEvaluableWithContext(c, expression)
86 if err != nil {
87 return nil, err
88 }
89 v, err := eval(c, parameter)
90 if err != nil {
91 return nil, fmt.Errorf("can not evaluate %s: %w", expression, err)
92 }
93 return v, nil
94 }
95
96
97
98
99
100
101
102
103 func Function(name string, function interface{}) Language {
104 l := newLanguage()
105 l.prefixes[name] = func(c context.Context, p *Parser) (eval Evaluable, err error) {
106 args := []Evaluable{}
107 scan := p.Scan()
108 switch scan {
109 case '(':
110 args, err = p.parseArguments(c)
111 if err != nil {
112 return nil, err
113 }
114 default:
115 p.Camouflage("function call", '(')
116 }
117 return p.callFunc(toFunc(function), args...), nil
118 }
119 return l
120 }
121
122
123 func Constant(name string, value interface{}) Language {
124 l := newLanguage()
125 l.prefixes[l.makePrefixKey(name)] = func(c context.Context, p *Parser) (eval Evaluable, err error) {
126 return p.Const(value), nil
127 }
128 return l
129 }
130
131
132 func PrefixExtension(r rune, ext func(context.Context, *Parser) (Evaluable, error)) Language {
133 l := newLanguage()
134 l.prefixes[r] = ext
135 return l
136 }
137
138
139
140
141
142
143
144 func Init(ext func(context.Context, *Parser) (Evaluable, error)) Language {
145 l := newLanguage()
146 l.init = ext
147 return l
148 }
149
150
151
152 func DefaultExtension(ext func(context.Context, *Parser) (Evaluable, error)) Language {
153 l := newLanguage()
154 l.def = ext
155 return l
156 }
157
158
159 func PrefixMetaPrefix(r rune, ext func(context.Context, *Parser) (call string, alternative func() (Evaluable, error), err error)) Language {
160 l := newLanguage()
161 l.prefixes[r] = func(c context.Context, p *Parser) (Evaluable, error) {
162 call, alternative, err := ext(c, p)
163 if err != nil {
164 return nil, err
165 }
166 if prefix, ok := p.prefixes[l.makePrefixKey(call)]; ok {
167 return prefix(c, p)
168 }
169 return alternative()
170 }
171 return l
172 }
173
174
175 func PrefixOperator(name string, e Evaluable) Language {
176 l := newLanguage()
177 l.prefixes[l.makePrefixKey(name)] = func(c context.Context, p *Parser) (Evaluable, error) {
178 eval, err := p.ParseNextExpression(c)
179 if err != nil {
180 return nil, err
181 }
182 prefix := func(c context.Context, v interface{}) (interface{}, error) {
183 a, err := eval(c, v)
184 if err != nil {
185 return nil, err
186 }
187 return e(c, a)
188 }
189 if eval.IsConst() {
190 v, err := prefix(c, nil)
191 if err != nil {
192 return nil, err
193 }
194 prefix = p.Const(v)
195 }
196 return prefix, nil
197 }
198 return l
199 }
200
201
202 func PostfixOperator(name string, ext func(context.Context, *Parser, Evaluable) (Evaluable, error)) Language {
203 l := newLanguage()
204 l.operators[l.makeInfixKey(name)] = postfix{
205 f: func(c context.Context, p *Parser, eval Evaluable, pre operatorPrecedence) (Evaluable, error) {
206 return ext(c, p, eval)
207 },
208 }
209 return l
210 }
211
212
213 func InfixOperator(name string, f func(a, b interface{}) (interface{}, error)) Language {
214 return newLanguageOperator(name, &infix{arbitrary: f})
215 }
216
217
218 func InfixShortCircuit(name string, f func(a interface{}) (interface{}, bool)) Language {
219 return newLanguageOperator(name, &infix{shortCircuit: f})
220 }
221
222
223 func InfixTextOperator(name string, f func(a, b string) (interface{}, error)) Language {
224 return newLanguageOperator(name, &infix{text: f})
225 }
226
227
228 func InfixNumberOperator(name string, f func(a, b float64) (interface{}, error)) Language {
229 return newLanguageOperator(name, &infix{number: f})
230 }
231
232
233 func InfixDecimalOperator(name string, f func(a, b decimal.Decimal) (interface{}, error)) Language {
234 return newLanguageOperator(name, &infix{decimal: f})
235 }
236
237
238 func InfixBoolOperator(name string, f func(a, b bool) (interface{}, error)) Language {
239 return newLanguageOperator(name, &infix{boolean: f})
240 }
241
242
243 func Precedence(name string, operatorPrecendence uint8) Language {
244 return newLanguageOperator(name, operatorPrecedence(operatorPrecendence))
245 }
246
247
248
249 func InfixEvalOperator(name string, f func(a, b Evaluable) (Evaluable, error)) Language {
250 return newLanguageOperator(name, directInfix{infixBuilder: f})
251 }
252
253 func newLanguageOperator(name string, op operator) Language {
254 op.initiate(name)
255 l := newLanguage()
256 l.operators[l.makeInfixKey(name)] = op
257 return l
258 }
259
260 func (l *Language) makePrefixKey(key string) interface{} {
261 runes := []rune(key)
262 if len(runes) == 1 && !unicode.IsLetter(runes[0]) {
263 return runes[0]
264 }
265 return key
266 }
267
268 func (l *Language) makeInfixKey(key string) string {
269 for _, r := range key {
270 l.operatorSymbols[r] = struct{}{}
271 }
272 return key
273 }
274
275
276
277 func VariableSelector(selector func(path Evaluables) Evaluable) Language {
278 l := newLanguage()
279 l.selector = selector
280 return l
281 }
282
View as plain text