/
tmpl.go
91 lines (73 loc) · 1.63 KB
/
tmpl.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
86
87
88
89
90
91
package main
import (
"bytes"
"fmt"
"go/format"
"io"
"text/template"
)
var tmpl = template.New("code")
func init() {
token := func(t Token) string {
switch t := t.(type) {
case Term:
return fmt.Sprintf("newTerm(%q)", t)
case NTerm:
return fmt.Sprintf("newNTerm(%q)", t[1:len(t)-1])
case Epsilon:
return "newEpsilon()"
case EOF:
return "newEOF()"
}
panic(fmt.Errorf("Unexpected token type: %T", t))
}
tmpl.Funcs(template.FuncMap{
"isEpsilon": isEpsilon,
"token": token,
"rule": func(r Rule) string {
var buf bytes.Buffer
buf.WriteString("newRule(")
var s string
for _, t := range r {
buf.WriteString(s)
buf.WriteString(token(t))
s = ", "
}
buf.WriteRune(')')
return buf.String()
},
})
tmpl = template.Must(tmpl.Parse(`// Code generated by pgen. DO NOT EDIT.
package pgen
var Table = map[Lookup]Rule{
{{ range $nterm, $_ := . }}
{{- range $term, $from := $.First $nterm -}}
{{- if isEpsilon $term | not -}}
{Term: {{ $term | token }}, NTerm: {{ $nterm | token -}} }: {{ $from | rule }},
{{ end -}}
{{ end -}}
{{- if $.Nullable $nterm -}}
{{- range $term, $from := $.Follow $nterm -}}
{{- if isEpsilon $term | not -}}
{Term: {{ $term | token }}, NTerm: {{ $nterm | token -}} }: newRule(newEpsilon()),
{{ end -}}
{{ end -}}
{{ end -}}
{{ end }}
}`))
}
type formatter struct {
w io.Writer
buf bytes.Buffer
}
func (f *formatter) Write(data []byte) (int, error) {
return f.buf.Write(data)
}
func (f formatter) Close() error {
src, err := format.Source(f.buf.Bytes())
if err != nil {
return err
}
_, err = f.w.Write(src)
return err
}