-
Notifications
You must be signed in to change notification settings - Fork 19
/
base.go
59 lines (47 loc) · 1.49 KB
/
base.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
package excellent
import (
"strings"
"github.com/nyaruka/goflow/excellent/gen"
"github.com/antlr/antlr4/runtime/Go/antlr"
)
// VisitExpression parses and visits the given expression with the given visitor
func VisitExpression(expression string, visitor antlr.ParseTreeVisitor) (interface{}, error) {
errListener := NewErrorListener(expression)
input := antlr.NewInputStream(expression)
lexer := gen.NewExcellent2Lexer(input)
stream := antlr.NewCommonTokenStream(lexer, 0)
p := gen.NewExcellent2Parser(stream)
p.RemoveErrorListeners()
p.AddErrorListener(errListener)
tree := p.Parse()
// if we ran into errors parsing, return the first one
if len(errListener.Errors()) > 0 {
return nil, errListener.Errors()[0]
}
return visitor.Visit(tree), nil
}
// VisitTemplate scans the given template and calls the callback for each token encountered
func VisitTemplate(template string, allowedTopLevels []string, callback func(XTokenType, string) error) error {
// nothing todo for an empty template
if template == "" {
return nil
}
scanner := NewXScanner(strings.NewReader(template), allowedTopLevels)
errors := NewTemplateErrors()
for tokenType, token := scanner.Scan(); tokenType != EOF; tokenType, token = scanner.Scan() {
err := callback(tokenType, token)
if err != nil {
var repr string
if tokenType == IDENTIFIER {
repr = "@" + token
} else {
repr = "@(" + token + ")"
}
errors.Add(repr, err.Error())
}
}
if errors.HasErrors() {
return errors
}
return nil
}