racc 1.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitattributes +2 -0
- data/.gitignore +7 -0
- data/COPYING +515 -0
- data/ChangeLog +846 -0
- data/DEPENDS +4 -0
- data/README.en.rdoc +86 -0
- data/README.ja.rdoc +96 -0
- data/Rakefile +15 -0
- data/TODO +5 -0
- data/bin/racc +308 -0
- data/bin/racc2y +195 -0
- data/bin/y2racc +339 -0
- data/doc/en/NEWS.en.rdoc +282 -0
- data/doc/en/command.en.html +78 -0
- data/doc/en/debug.en.rdoc +20 -0
- data/doc/en/grammar.en.rdoc +230 -0
- data/doc/en/index.en.html +10 -0
- data/doc/en/parser.en.rdoc +74 -0
- data/doc/en/usage.en.html +92 -0
- data/doc/ja/NEWS.ja.rdoc +307 -0
- data/doc/ja/command.ja.html +94 -0
- data/doc/ja/debug.ja.rdoc +36 -0
- data/doc/ja/grammar.ja.rdoc +348 -0
- data/doc/ja/index.ja.html +10 -0
- data/doc/ja/parser.ja.rdoc +125 -0
- data/doc/ja/usage.ja.html +414 -0
- data/ext/racc/cparse/MANIFEST +4 -0
- data/ext/racc/cparse/cparse.c +824 -0
- data/ext/racc/cparse/depend +1 -0
- data/ext/racc/cparse/extconf.rb +7 -0
- data/fastcache/extconf.rb +2 -0
- data/fastcache/fastcache.c +185 -0
- data/lib/racc.rb +6 -0
- data/lib/racc/compat.rb +40 -0
- data/lib/racc/debugflags.rb +59 -0
- data/lib/racc/exception.rb +15 -0
- data/lib/racc/grammar.rb +1115 -0
- data/lib/racc/grammarfileparser.rb +559 -0
- data/lib/racc/info.rb +16 -0
- data/lib/racc/iset.rb +91 -0
- data/lib/racc/logfilegenerator.rb +214 -0
- data/lib/racc/parser.rb +439 -0
- data/lib/racc/parserfilegenerator.rb +511 -0
- data/lib/racc/pre-setup +13 -0
- data/lib/racc/sourcetext.rb +34 -0
- data/lib/racc/state.rb +971 -0
- data/lib/racc/statetransitiontable.rb +316 -0
- data/lib/racc/static.rb +5 -0
- data/misc/dist.sh +31 -0
- data/sample/array.y +67 -0
- data/sample/array2.y +59 -0
- data/sample/calc-ja.y +66 -0
- data/sample/calc.y +65 -0
- data/sample/conflict.y +15 -0
- data/sample/hash.y +60 -0
- data/sample/lalr.y +17 -0
- data/sample/lists.y +57 -0
- data/sample/syntax.y +46 -0
- data/sample/yyerr.y +46 -0
- data/setup.rb +1587 -0
- data/tasks/doc.rb +12 -0
- data/tasks/email.rb +55 -0
- data/tasks/file.rb +37 -0
- data/tasks/gem.rb +37 -0
- data/tasks/test.rb +16 -0
- data/test/assets/chk.y +126 -0
- data/test/assets/conf.y +16 -0
- data/test/assets/digraph.y +29 -0
- data/test/assets/echk.y +118 -0
- data/test/assets/err.y +60 -0
- data/test/assets/expect.y +7 -0
- data/test/assets/firstline.y +4 -0
- data/test/assets/ichk.y +102 -0
- data/test/assets/intp.y +546 -0
- data/test/assets/mailp.y +437 -0
- data/test/assets/newsyn.y +25 -0
- data/test/assets/noend.y +4 -0
- data/test/assets/nonass.y +41 -0
- data/test/assets/normal.y +27 -0
- data/test/assets/norule.y +4 -0
- data/test/assets/nullbug1.y +25 -0
- data/test/assets/nullbug2.y +15 -0
- data/test/assets/opt.y +123 -0
- data/test/assets/percent.y +35 -0
- data/test/assets/recv.y +97 -0
- data/test/assets/rrconf.y +14 -0
- data/test/assets/scan.y +72 -0
- data/test/assets/syntax.y +50 -0
- data/test/assets/unterm.y +5 -0
- data/test/assets/useless.y +12 -0
- data/test/assets/yyerr.y +46 -0
- data/test/bench.y +36 -0
- data/test/helper.rb +88 -0
- data/test/infini.y +8 -0
- data/test/scandata/brace +7 -0
- data/test/scandata/gvar +1 -0
- data/test/scandata/normal +4 -0
- data/test/scandata/percent +18 -0
- data/test/scandata/slash +10 -0
- data/test/src.intp +34 -0
- data/test/start.y +20 -0
- data/test/test_chk_y.rb +51 -0
- data/test/test_grammar_file_parser.rb +15 -0
- data/test/test_racc_command.rb +155 -0
- data/test/test_scan_y.rb +51 -0
- data/test/testscanner.rb +51 -0
- data/web/racc.en.rhtml +42 -0
- data/web/racc.ja.rhtml +51 -0
- metadata +166 -0
@@ -0,0 +1,316 @@
|
|
1
|
+
#
|
2
|
+
# $Id$
|
3
|
+
#
|
4
|
+
# Copyright (c) 1999-2006 Minero Aoki
|
5
|
+
#
|
6
|
+
# This program is free software.
|
7
|
+
# You can distribute/modify this program under the terms of
|
8
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
9
|
+
# For details of LGPL, see the file "COPYING".
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'racc/parser'
|
13
|
+
|
14
|
+
unless Object.method_defined?(:funcall)
|
15
|
+
class Object
|
16
|
+
alias funcall __send__
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Racc
|
21
|
+
|
22
|
+
StateTransitionTable = Struct.new(:action_table,
|
23
|
+
:action_check,
|
24
|
+
:action_default,
|
25
|
+
:action_pointer,
|
26
|
+
:goto_table,
|
27
|
+
:goto_check,
|
28
|
+
:goto_default,
|
29
|
+
:goto_pointer,
|
30
|
+
:token_table,
|
31
|
+
:reduce_table,
|
32
|
+
:reduce_n,
|
33
|
+
:shift_n,
|
34
|
+
:nt_base,
|
35
|
+
:token_to_s_table,
|
36
|
+
:use_result_var,
|
37
|
+
:debug_parser)
|
38
|
+
class StateTransitionTable # reopen
|
39
|
+
def StateTransitionTable.generate(states)
|
40
|
+
StateTransitionTableGenerator.new(states).generate
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize(states)
|
44
|
+
super()
|
45
|
+
@states = states
|
46
|
+
@grammar = states.grammar
|
47
|
+
self.use_result_var = true
|
48
|
+
self.debug_parser = true
|
49
|
+
end
|
50
|
+
|
51
|
+
attr_reader :states
|
52
|
+
attr_reader :grammar
|
53
|
+
|
54
|
+
def parser_class
|
55
|
+
ParserClassGenerator.new(@states).generate
|
56
|
+
end
|
57
|
+
|
58
|
+
def token_value_table
|
59
|
+
h = {}
|
60
|
+
token_table().each do |sym, i|
|
61
|
+
h[sym.value] = i
|
62
|
+
end
|
63
|
+
h
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
class StateTransitionTableGenerator
|
69
|
+
|
70
|
+
def initialize(states)
|
71
|
+
@states = states
|
72
|
+
@grammar = states.grammar
|
73
|
+
end
|
74
|
+
|
75
|
+
def generate
|
76
|
+
t = StateTransitionTable.new(@states)
|
77
|
+
gen_action_tables t, @states
|
78
|
+
gen_goto_tables t, @grammar
|
79
|
+
t.token_table = token_table(@grammar)
|
80
|
+
t.reduce_table = reduce_table(@grammar)
|
81
|
+
t.reduce_n = @states.reduce_n
|
82
|
+
t.shift_n = @states.shift_n
|
83
|
+
t.nt_base = @grammar.nonterminal_base
|
84
|
+
t.token_to_s_table = @grammar.symbols.map {|sym| sym.to_s }
|
85
|
+
t
|
86
|
+
end
|
87
|
+
|
88
|
+
def reduce_table(grammar)
|
89
|
+
t = [0, 0, :racc_error]
|
90
|
+
grammar.each_with_index do |rule, idx|
|
91
|
+
next if idx == 0
|
92
|
+
t.push rule.size
|
93
|
+
t.push rule.target.ident
|
94
|
+
t.push(if rule.action.empty? # and @params.omit_action_call?
|
95
|
+
then :_reduce_none
|
96
|
+
else "_reduce_#{idx}".intern
|
97
|
+
end)
|
98
|
+
end
|
99
|
+
t
|
100
|
+
end
|
101
|
+
|
102
|
+
def token_table(grammar)
|
103
|
+
h = {}
|
104
|
+
grammar.symboltable.terminals.each do |t|
|
105
|
+
h[t] = t.ident
|
106
|
+
end
|
107
|
+
h
|
108
|
+
end
|
109
|
+
|
110
|
+
def gen_action_tables(t, states)
|
111
|
+
t.action_table = yytable = []
|
112
|
+
t.action_check = yycheck = []
|
113
|
+
t.action_default = yydefact = []
|
114
|
+
t.action_pointer = yypact = []
|
115
|
+
e1 = []
|
116
|
+
e2 = []
|
117
|
+
states.each do |state|
|
118
|
+
yydefact.push act2actid(state.defact)
|
119
|
+
if state.action.empty?
|
120
|
+
yypact.push nil
|
121
|
+
next
|
122
|
+
end
|
123
|
+
vector = []
|
124
|
+
state.action.each do |tok, act|
|
125
|
+
vector[tok.ident] = act2actid(act)
|
126
|
+
end
|
127
|
+
addent e1, vector, state.ident, yypact
|
128
|
+
end
|
129
|
+
set_table e1, e2, yytable, yycheck, yypact
|
130
|
+
end
|
131
|
+
|
132
|
+
def gen_goto_tables(t, grammar)
|
133
|
+
t.goto_table = yytable2 = []
|
134
|
+
t.goto_check = yycheck2 = []
|
135
|
+
t.goto_pointer = yypgoto = []
|
136
|
+
t.goto_default = yydefgoto = []
|
137
|
+
e1 = []
|
138
|
+
e2 = []
|
139
|
+
grammar.each_nonterminal do |tok|
|
140
|
+
tmp = []
|
141
|
+
|
142
|
+
# decide default
|
143
|
+
freq = Array.new(@states.size, 0)
|
144
|
+
@states.each do |state|
|
145
|
+
st = state.goto_table[tok]
|
146
|
+
if st
|
147
|
+
st = st.ident
|
148
|
+
freq[st] += 1
|
149
|
+
end
|
150
|
+
tmp[state.ident] = st
|
151
|
+
end
|
152
|
+
max = freq.max
|
153
|
+
if max > 1
|
154
|
+
default = freq.index(max)
|
155
|
+
tmp.map! {|i| default == i ? nil : i }
|
156
|
+
else
|
157
|
+
default = nil
|
158
|
+
end
|
159
|
+
yydefgoto.push default
|
160
|
+
|
161
|
+
# delete default value
|
162
|
+
tmp.pop until tmp.last or tmp.empty?
|
163
|
+
if tmp.compact.empty?
|
164
|
+
# only default
|
165
|
+
yypgoto.push nil
|
166
|
+
next
|
167
|
+
end
|
168
|
+
|
169
|
+
addent e1, tmp, (tok.ident - grammar.nonterminal_base), yypgoto
|
170
|
+
end
|
171
|
+
set_table e1, e2, yytable2, yycheck2, yypgoto
|
172
|
+
end
|
173
|
+
|
174
|
+
def addent(all, arr, chkval, ptr)
|
175
|
+
max = arr.size
|
176
|
+
min = nil
|
177
|
+
arr.each_with_index do |item, idx|
|
178
|
+
if item
|
179
|
+
min ||= idx
|
180
|
+
end
|
181
|
+
end
|
182
|
+
ptr.push(-7777) # mark
|
183
|
+
arr = arr[min...max]
|
184
|
+
all.push [arr, chkval, mkmapexp(arr), min, ptr.size - 1]
|
185
|
+
end
|
186
|
+
|
187
|
+
n = 2 ** 16
|
188
|
+
begin
|
189
|
+
Regexp.compile("a{#{n}}")
|
190
|
+
RE_DUP_MAX = n
|
191
|
+
rescue RegexpError
|
192
|
+
n /= 2
|
193
|
+
retry
|
194
|
+
end
|
195
|
+
|
196
|
+
def mkmapexp(arr)
|
197
|
+
i = ii = 0
|
198
|
+
as = arr.size
|
199
|
+
map = ''
|
200
|
+
maxdup = RE_DUP_MAX
|
201
|
+
curr = nil
|
202
|
+
while i < as
|
203
|
+
ii = i + 1
|
204
|
+
if arr[i]
|
205
|
+
ii += 1 while ii < as and arr[ii]
|
206
|
+
curr = '-'
|
207
|
+
else
|
208
|
+
ii += 1 while ii < as and not arr[ii]
|
209
|
+
curr = '.'
|
210
|
+
end
|
211
|
+
|
212
|
+
offset = ii - i
|
213
|
+
if offset == 1
|
214
|
+
map << curr
|
215
|
+
else
|
216
|
+
while offset > maxdup
|
217
|
+
map << "#{curr}{#{maxdup}}"
|
218
|
+
offset -= maxdup
|
219
|
+
end
|
220
|
+
map << "#{curr}{#{offset}}" if offset > 1
|
221
|
+
end
|
222
|
+
i = ii
|
223
|
+
end
|
224
|
+
Regexp.compile(map, 'n')
|
225
|
+
end
|
226
|
+
|
227
|
+
def set_table(entries, dummy, tbl, chk, ptr)
|
228
|
+
upper = 0
|
229
|
+
map = '-' * 10240
|
230
|
+
|
231
|
+
# sort long to short
|
232
|
+
entries.sort! {|a,b| b[0].size <=> a[0].size }
|
233
|
+
|
234
|
+
entries.each do |arr, chkval, expr, min, ptri|
|
235
|
+
if upper + arr.size > map.size
|
236
|
+
map << '-' * (arr.size + 1024)
|
237
|
+
end
|
238
|
+
idx = map.index(expr)
|
239
|
+
ptr[ptri] = idx - min
|
240
|
+
arr.each_with_index do |item, i|
|
241
|
+
if item
|
242
|
+
i += idx
|
243
|
+
tbl[i] = item
|
244
|
+
chk[i] = chkval
|
245
|
+
map[i] = ?o
|
246
|
+
end
|
247
|
+
end
|
248
|
+
upper = idx + arr.size
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def act2actid(act)
|
253
|
+
case act
|
254
|
+
when Shift then act.goto_id
|
255
|
+
when Reduce then -act.ruleid
|
256
|
+
when Accept then @states.shift_n
|
257
|
+
when Error then @states.reduce_n * -1
|
258
|
+
else
|
259
|
+
raise "racc: fatal: wrong act type #{act.class} in action table"
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
|
266
|
+
class ParserClassGenerator
|
267
|
+
|
268
|
+
def initialize(states)
|
269
|
+
@states = states
|
270
|
+
@grammar = states.grammar
|
271
|
+
end
|
272
|
+
|
273
|
+
def generate
|
274
|
+
table = @states.state_transition_table
|
275
|
+
c = Class.new(::Racc::Parser)
|
276
|
+
c.const_set :Racc_arg, [table.action_table,
|
277
|
+
table.action_check,
|
278
|
+
table.action_default,
|
279
|
+
table.action_pointer,
|
280
|
+
table.goto_table,
|
281
|
+
table.goto_check,
|
282
|
+
table.goto_default,
|
283
|
+
table.goto_pointer,
|
284
|
+
table.nt_base,
|
285
|
+
table.reduce_table,
|
286
|
+
table.token_value_table,
|
287
|
+
table.shift_n,
|
288
|
+
table.reduce_n,
|
289
|
+
false]
|
290
|
+
c.const_set :Racc_token_to_s_table, table.token_to_s_table
|
291
|
+
c.const_set :Racc_debug_parser, true
|
292
|
+
define_actions c
|
293
|
+
c
|
294
|
+
end
|
295
|
+
|
296
|
+
private
|
297
|
+
|
298
|
+
def define_actions(c)
|
299
|
+
c.module_eval "def _reduce_none(vals, vstack) vals[0] end"
|
300
|
+
@grammar.each do |rule|
|
301
|
+
if rule.action.empty?
|
302
|
+
c.funcall(:alias_method, "_reduce_#{rule.ident}", :_reduce_none)
|
303
|
+
else
|
304
|
+
c.funcall(:define_method, "_racc_action_#{rule.ident}", &rule.action.proc)
|
305
|
+
c.module_eval(s = <<-End, __FILE__, __LINE__ + 1)
|
306
|
+
def _reduce_#{rule.ident}(vals, vstack)
|
307
|
+
_racc_action_#{rule.ident}(*vals)
|
308
|
+
end
|
309
|
+
End
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
315
|
+
|
316
|
+
end # module Racc
|
data/lib/racc/static.rb
ADDED
data/misc/dist.sh
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
rm -rf tmp
|
4
|
+
mkdir tmp
|
5
|
+
cd tmp
|
6
|
+
|
7
|
+
# racc, raccrt
|
8
|
+
cvs -Q export -r`echo V$version | tr . -` -d racc-$version racc
|
9
|
+
cd racc-$version
|
10
|
+
make bootstrap lib/racc/parser-text.rb doc
|
11
|
+
rm -r doc web bits fastcache
|
12
|
+
cd ..
|
13
|
+
mkdir -p raccrt-$version/lib/racc
|
14
|
+
mv racc-$version/lib/racc/parser.rb raccrt-$version/lib/racc
|
15
|
+
mv racc-$version/ext raccrt-$version
|
16
|
+
cp racc-$version/setup.rb raccrt-$version
|
17
|
+
cp racc-$version/README.* raccrt-$version
|
18
|
+
cp racc-$version/COPYING raccrt-$version
|
19
|
+
tar czf $ardir/racc/racc-$version.tar.gz racc-$version
|
20
|
+
tar czf $ardir/raccrt/raccrt-$version.tar.gz raccrt-$version
|
21
|
+
|
22
|
+
# -all
|
23
|
+
mkdir -p racc-$version-all/packages
|
24
|
+
cp racc-$version/setup.rb racc-$version-all
|
25
|
+
cp racc-$version/README.* racc-$version-all
|
26
|
+
mv racc-$version racc-$version-all/packages/racc
|
27
|
+
mv raccrt-$version racc-$version-all/packages/raccrt
|
28
|
+
tar czf $ardir/racc/racc-$version-all.tar.gz racc-$version-all
|
29
|
+
|
30
|
+
cd ..
|
31
|
+
rm -rf tmp
|
data/sample/array.y
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# $Id$
|
2
|
+
#
|
3
|
+
# convert Array-like string into Ruby's Array.
|
4
|
+
|
5
|
+
class ArrayParser
|
6
|
+
|
7
|
+
rule
|
8
|
+
|
9
|
+
array : '[' contents ']'
|
10
|
+
{
|
11
|
+
result = val[1]
|
12
|
+
}
|
13
|
+
| '[' ']'
|
14
|
+
{
|
15
|
+
result = []
|
16
|
+
}
|
17
|
+
|
18
|
+
contents: ITEM
|
19
|
+
{
|
20
|
+
result = val
|
21
|
+
}
|
22
|
+
| contents ',' ITEM
|
23
|
+
{
|
24
|
+
result.push val[2]
|
25
|
+
}
|
26
|
+
|
27
|
+
---- inner
|
28
|
+
|
29
|
+
def parse(str)
|
30
|
+
str = str.strip
|
31
|
+
@q = []
|
32
|
+
until str.empty?
|
33
|
+
case str
|
34
|
+
when /\A\s+/
|
35
|
+
str = $'
|
36
|
+
when /\A\w+/
|
37
|
+
@q.push [:ITEM, $&]
|
38
|
+
str = $'
|
39
|
+
else
|
40
|
+
c = str[0,1]
|
41
|
+
@q.push [c, c]
|
42
|
+
str = str[1..-1]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
@q.push [false, '$'] # is optional from Racc 1.3.7
|
46
|
+
do_parse
|
47
|
+
end
|
48
|
+
|
49
|
+
def next_token
|
50
|
+
@q.shift
|
51
|
+
end
|
52
|
+
|
53
|
+
---- footer
|
54
|
+
|
55
|
+
if $0 == __FILE__
|
56
|
+
src = <<EOS
|
57
|
+
[
|
58
|
+
a, b, c,
|
59
|
+
d,
|
60
|
+
e ]
|
61
|
+
EOS
|
62
|
+
puts 'parsing:'
|
63
|
+
print src
|
64
|
+
puts
|
65
|
+
puts 'result:'
|
66
|
+
p ArrayParser.new.parse(src)
|
67
|
+
end
|
data/sample/array2.y
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# $Id$
|
2
|
+
#
|
3
|
+
# Converting Array-like string into Ruby's Array, version 2.
|
4
|
+
# This grammer uses no_result_var.
|
5
|
+
|
6
|
+
class ArrayParser2
|
7
|
+
options no_result_var
|
8
|
+
rule
|
9
|
+
array : '[' contents ']' { val[1] }
|
10
|
+
| '[' ']' { [] }
|
11
|
+
|
12
|
+
contents: ITEM { val }
|
13
|
+
| contents ',' ITEM { val[0].push val[2]; val[0] }
|
14
|
+
end
|
15
|
+
|
16
|
+
---- inner
|
17
|
+
|
18
|
+
def parse(str)
|
19
|
+
@str = str
|
20
|
+
yyparse self, :scan
|
21
|
+
end
|
22
|
+
|
23
|
+
def scan
|
24
|
+
str = @str.strip
|
25
|
+
until str.empty?
|
26
|
+
case str
|
27
|
+
when /\A\s+/
|
28
|
+
str = $'
|
29
|
+
when /\A\w+/
|
30
|
+
yield :ITEM, $&
|
31
|
+
str = $'
|
32
|
+
else
|
33
|
+
c = str[0,1]
|
34
|
+
yield c, c
|
35
|
+
str = str[1..-1]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
yield false, '$' # is optional from Racc 1.3.7
|
39
|
+
end
|
40
|
+
|
41
|
+
def next_token
|
42
|
+
@q.shift
|
43
|
+
end
|
44
|
+
|
45
|
+
---- footer
|
46
|
+
|
47
|
+
if $0 == __FILE__
|
48
|
+
src = <<EOS
|
49
|
+
[
|
50
|
+
a, b, c,
|
51
|
+
d,
|
52
|
+
e ]
|
53
|
+
EOS
|
54
|
+
puts 'parsing:'
|
55
|
+
print src
|
56
|
+
puts
|
57
|
+
puts 'result:'
|
58
|
+
p ArrayParser2.new.parse(src)
|
59
|
+
end
|