forked from yukirii/go-tmsh
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.go.y
155 lines (132 loc) · 2.17 KB
/
parser.go.y
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
%{
package tmsh
import (
"fmt"
)
const (
ltmNodeNode = iota
ltmPoolNode
ltmVirtualNode
keyNode
structNode
scalarNode
)
type nodeType int
type node struct {
kind nodeType
value string
children []*node
}
type Token struct {
token int
literal string
}
%}
%union{
token Token
ltm *node
object *node
pair *node
members []*node
value *node
}
%type<ltm> ltm
%type<object> object
%type<pair> pair
%type<members> members
%type<value> value
%token<token> ILLEGAL
%token<token> EOF
%token<token> WS
%token<token> NEWLINE
%token<token> L_BRACE
%token<token> R_BRACE
%token<token> IDENT
%token<token> LTM
%%
ltm
: LTM IDENT IDENT object
{
var kind nodeType
switch $2.literal {
case "node":
kind = ltmNodeNode
case "pool":
kind = ltmPoolNode
case "virtual":
kind = ltmVirtualNode
}
yylex.(*Lexer).result = &node{
kind: kind,
value: $3.literal,
children: []*node{$4},
}
}
object
: L_BRACE R_BRACE
{
$$ = &node{kind: structNode, value: "", children: []*node{}}
}
| L_BRACE NEWLINE R_BRACE
{
$$ = &node{kind: structNode, value: "", children: []*node{}}
}
| L_BRACE NEWLINE members R_BRACE
{
$$ = &node{kind: structNode, value: "", children: $3}
}
members
: pair
{
$$ = []*node{$1}
}
| members pair
{
$$ = append($1, $2)
}
pair
: IDENT NEWLINE
{
$$ = &node{kind: keyNode, value: $1.literal, children: []*node{}}
}
| IDENT value NEWLINE
{
$$ = &node{kind: keyNode, value: $1.literal, children: []*node{$2}}
}
| IDENT object NEWLINE
{
$$ = &node{kind: keyNode, value: $1.literal, children: []*node{$2}}
}
value
: IDENT value
{
s := fmt.Sprintf("%s %s", $1.literal, $2.value)
$$ = &node{kind: scalarNode, value: s, children: []*node{}}
}
| IDENT
{
$$ = &node{kind: scalarNode, value: $1.literal, children: []*node{}}
}
%%
type Lexer struct {
s *scanner
result *node
}
func (l *Lexer) Lex(lval *yySymType) int {
var tok int
var lit string
for {
tok, lit = l.s.Scan()
if tok != WS {
break
}
}
lval.token = Token{token: tok, literal: lit}
if tok == EOF {
return 0
}
return tok
}
func (l *Lexer) Error(e string) {
panic(fmt.Sprintf("line %d : %s", l.s.line, e))
}