forked from earthly/earthly
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathast.go
More file actions
84 lines (75 loc) · 2.38 KB
/
Copy pathast.go
File metadata and controls
84 lines (75 loc) · 2.38 KB
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
package ast
import (
"context"
"fmt"
"strings"
"github.com/antlr/antlr4/runtime/Go/antlr"
"github.com/earthly/earthly/ast/antlrhandler"
"github.com/earthly/earthly/ast/parser"
"github.com/earthly/earthly/ast/spec"
"github.com/pkg/errors"
)
// Parse parses an earthfile into an AST.
func Parse(ctx context.Context, filePath string, enableSourceMap bool) (ef spec.Earthfile, err error) {
version, err := ParseVersion(filePath, enableSourceMap)
if err != nil {
return spec.Earthfile{}, err
}
// Convert.
errorListener := antlrhandler.NewReturnErrorListener()
errorStrategy := antlrhandler.NewReturnErrorStrategy()
tree, err := newEarthfileTree(filePath, errorListener, errorStrategy)
if err != nil {
return spec.Earthfile{}, err
}
ef, walkErr := walkTree(newListener(ctx, filePath, enableSourceMap), tree)
if len(errorListener.Errs) > 0 {
errString := []string{fmt.Sprintf("lexer error: %s", filePath)}
for _, err := range errorListener.Errs {
errString = append(errString, err.Error())
}
return spec.Earthfile{}, errors.Errorf(strings.Join(errString, "\n"))
}
if errorStrategy.Err != nil {
return spec.Earthfile{}, errors.Wrapf(
errorStrategy.Err, "%s line %d:%d '%s'",
filePath,
errorStrategy.RE.GetOffendingToken().GetLine(),
errorStrategy.RE.GetOffendingToken().GetColumn(),
errorStrategy.RE.GetOffendingToken().GetText())
}
if walkErr != nil {
return spec.Earthfile{}, walkErr
}
ef.Version = version
if err := validateAst(ef); err != nil {
return spec.Earthfile{}, err
}
return ef, nil
}
func walkTree(l *listener, tree parser.IEarthFileContext) (spec.Earthfile, error) {
antlr.ParseTreeWalkerDefault.Walk(l, tree)
err := l.Err()
if err != nil {
return spec.Earthfile{}, err
}
return l.Earthfile(), nil
}
func newEarthfileTree(filename string, errorListener *antlrhandler.ReturnErrorListener, errorStrategy antlr.ErrorStrategy) (parser.IEarthFileContext, error) {
input, err := antlr.NewFileStream(filename)
if err != nil {
return nil, errors.Wrapf(err, "new file stream %s", filename)
}
lexer := newLexer(input)
lexer.RemoveErrorListeners()
lexer.AddErrorListener(errorListener)
stream := antlr.NewCommonTokenStream(lexer, 0)
if lexer.Err() != nil {
return nil, lexer.Err()
}
p := parser.NewEarthParser(stream)
p.AddErrorListener(errorListener)
p.SetErrorHandler(errorStrategy)
p.BuildParseTrees = true
return p.EarthFile(), nil
}