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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
# vim: syntax=ruby
class Nagios::Parser
token DEFINE NAME STRING PARAM LCURLY RCURLY VALUE RETURN COMMENT INLINECOMMENT
rule
decls: decl { return val[0] if val[0] }
| decls decl {
if val[1].nil?
result = val[0]
else
if val[0].nil?
result = val[1]
else
result = [ val[0], val[1] ].flatten
end
end
}
;
decl: object { result = [val[0]] }
| RETURN { result = nil }
| comment
;
comment: COMMENT RETURN { result = nil }
;
object: DEFINE NAME LCURLY RETURN vars RCURLY {
result = Nagios::Base.create(val[1],val[4])
}
;
vars: var
| vars var {
val[1].each {|p,v|
val[0][p] = v
}
result = val[0]
}
;
var: PARAM VALUE icomment returns { result = {val[0],val[1]} }
;
returns: RETURN
| returns RETURN
;
icomment: # nothing
| INLINECOMMENT
;
end
----inner
class ::Nagios::Parser::SyntaxError < RuntimeError; end
def parse(src)
@src = src
# state variables
@invar = false
@inobject = false
@done = false
@line = 0
@yydebug = true
do_parse
end
# The lexer. Very simple.
def token
@src.sub!(/\A\n/,'')
if $&
@line += 1
return [ :RETURN, "\n" ]
end
if @done
return nil
end
yytext = String.new
# remove comments from this line
@src.sub!(/\A[ \t]*;.*\n/,"\n")
if $&
return [:INLINECOMMENT, ""]
end
@src.sub!(/\A#.*\n/,"\n")
if $&
return [:COMMENT, ""]
end
@src.sub!(/#.*/,'')
if @src.length == 0
@done = true
return [false, '$']
end
if @invar
@src.sub!(/\A[ \t]+/,'')
@src.sub!(/\A([^;\n]+)(\n|;)/,'\2')
if $1
yytext += $1
end
@invar = false
return [:VALUE, yytext]
else
@src.sub!(/\A[\t ]*(\S+)([\t ]*|$)/,'')
if $1
yytext = $1
case yytext
when 'define'
#puts "got define"
return [:DEFINE, yytext]
when '{'
#puts "got {"
@inobject = true
return [:LCURLY, yytext]
else
unless @inobject
#puts "got type: #{yytext}"
if yytext =~ /\W/
giveback = yytext.dup
giveback.sub!(/^\w+/,'')
#puts "giveback " + giveback
#puts "yytext " + yytext
yytext.sub!(/\W.*$/,'')
#puts "yytext " + yytext
#puts "all [#{giveback} #{yytext} #{orig}]"
@src = giveback + @src
end
return [:NAME, yytext]
else
if yytext == '}'
#puts "got closure: #{yytext}"
@inobject = false
return [:RCURLY, '}']
end
unless @invar
@invar = true
return [:PARAM, $1]
else
end
end
end
end
end
end
def next_token
token
end
def yydebug
1
end
def yywrap
0
end
def on_error(token, value, vstack )
msg = ""
unless value.nil?
msg = "line #{@line}: syntax error at '#{value}'"
else
msg = "line #{@line}: syntax error at '#{token}'"
end
unless @src.size > 0
msg = "line #{@line}: Unexpected end of file"
end
if token == '$end'.intern
puts "okay, this is silly"
else
raise ::Nagios::Parser::SyntaxError, msg
end
end
|