-
Notifications
You must be signed in to change notification settings - Fork 0
/
bnf_parser.go
74 lines (67 loc) · 1.5 KB
/
bnf_parser.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
package main
import (
"encoding/xml"
"io"
"log"
"reflect"
)
type bnfParser struct {
}
func newBNFParser() bnfParser {
return bnfParser{}
}
func (p *bnfParser) parse(r io.Reader) *node {
decoder := xml.NewDecoder(r)
return p.buildTree(decoder)
}
func (p *bnfParser) buildTree(decoder *xml.Decoder) *node {
var root, current *node
for token, err := decoder.Token(); err == nil; token, err = decoder.Token() {
switch v := token.(type) {
case xml.StartElement:
current = p.handleStartElement(v, current)
if root == nil {
root = current
}
case xml.EndElement:
current = current.parent
case xml.ProcInst:
case xml.CharData:
if current != nil {
switch current.kind {
case kwKind:
current.value = string(v)
case terminalSymbolKind:
current.value = string(v)
default:
}
}
case xml.Comment:
case xml.Directive:
default:
log.Fatalf("from buildGraph'case %s:' not handled\n", reflect.TypeOf(v))
}
}
return root
}
func (b *bnfParser) handleStartElement(start xml.StartElement, parent *node) *node {
n := &node{
kind: start.Name.Local,
parent: parent,
children: make([]*node, 0),
}
if n.kind == bnfDefKind || n.kind == bnfKind {
n.name = b.attrMap(start.Attr)["name"]
}
if parent != nil {
parent.children = append(parent.children, n)
}
return n
}
func (b *bnfParser) attrMap(attrs []xml.Attr) map[string]string {
attrMap := make(map[string]string)
for _, attr := range attrs {
attrMap[attr.Name.Local] = attr.Value
}
return attrMap
}