depager 0.3.0.b20160729 → 0.3.0.b20250423
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.
- checksums.yaml +5 -5
- data/.rubocop.yml +44 -0
- data/.simplecov +5 -0
- data/Gemfile +12 -0
- data/LICENSE.gpl +339 -0
- data/Manifest.txt +73 -0
- data/README.en +4 -3
- data/README.ja +4 -47
- data/Rakefile +31 -0
- data/bin/depager +3 -38
- data/examples/action_pl0d/pl0d.action.dr +4 -4
- data/examples/action_pl0d/test.pl0ds +2 -3
- data/examples/c89/c89.dr +4 -4
- data/examples/c89/test.c89 +1 -1
- data/examples/extension/astdf.rb +4 -5
- data/examples/extension/atree.dr +3 -3
- data/examples/extension/calc.atree.dr +4 -4
- data/examples/extension/calc.simple_action.dr +3 -3
- data/examples/extension/paction.dr +3 -3
- data/examples/extension/pactiontest.dr +3 -3
- data/examples/extension/simple_action.rb +26 -24
- data/examples/pl0d/pl0ds.dr +5 -5
- data/examples/pl0d/test.pl0ds +2 -2
- data/examples/rie_calc/calc.rie.dr +4 -4
- data/examples/rie_dcuse/dcuse.rie.dr +4 -4
- data/examples/rie_pl0/pl0.rie.dr +3 -3
- data/examples/slex_test/divreg.slex.dr +5 -5
- data/examples/slex_test/ljoin.slex.dr +5 -5
- data/examples/{sample_calc → tiny_calc}/calc.action.dr +4 -4
- data/examples/{sample_calc → tiny_calc}/calc.ast.action.dr +20 -9
- data/examples/{sample_calc → tiny_calc}/calc.ast.dr +19 -7
- data/examples/{sample_calc → tiny_calc}/calc.cst.dr +12 -7
- data/examples/{sample_calc → tiny_calc}/calc.dr +1 -1
- data/examples/{sample_calc → tiny_calc}/calc.lex.dr +2 -2
- data/examples/{sample_calc → tiny_calc}/calc_prec.action.dr +4 -4
- data/lib/depager/cli.rb +44 -0
- data/lib/depager/grammar.rb +72 -75
- data/lib/depager/lr.rb +169 -154
- data/lib/depager/parser.rb +90 -103
- data/lib/depager/plugins/_rie_debug.rb +63 -0
- data/lib/depager/plugins/action.rb +47 -0
- data/lib/depager/{ruby/plugins → plugins}/ast.dr +20 -17
- data/lib/depager/{ruby/plugins → plugins}/ast.rb +266 -304
- data/lib/depager/{ruby/plugins → plugins}/cst.dr +18 -16
- data/lib/depager/{ruby/plugins → plugins}/cst.rb +152 -148
- data/lib/depager/{ruby/plugins → plugins}/lex.dr +7 -7
- data/lib/depager/{ruby/plugins → plugins}/lex.rb +72 -69
- data/lib/depager/{ruby/plugins → plugins}/rie.dr +12 -10
- data/lib/depager/{ruby/plugins → plugins}/rie.rb +224 -263
- data/lib/depager/{ruby/plugins → plugins}/slex.dr +13 -14
- data/lib/depager/{ruby/plugins → plugins}/slex.rb +183 -194
- data/lib/depager/plugins/srp.rb +46 -0
- data/lib/depager/ruby/templates/extension_lalr_master.erb +6 -12
- data/lib/depager/ruby/templates/extension_lalr_slave.erb +31 -17
- data/lib/depager/ruby/templates/single_lalr_parser.erb +35 -26
- data/lib/depager/utils.rb +56 -46
- data/lib/depager/version.rb +1 -2
- data/lib/depager.rb +166 -176
- metadata +38 -33
- data/lib/depager/ruby/plugins/_rie_debug.rb +0 -35
- data/lib/depager/ruby/plugins/action.rb +0 -53
- data/lib/depager/ruby/plugins/srp.rb +0 -56
- /data/examples/{sample_calc → tiny_calc}/test.calc +0 -0
data/lib/depager/parser.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../ruby", __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
1
|
+
require "forwardable"
|
4
2
|
|
5
3
|
module Depager
|
4
|
+
def self.path_of(io)
|
5
|
+
return "-" if io == $stdin
|
6
|
+
return "<#{io.class}>" unless io.respond_to?(:path) # StringIO
|
7
|
+
|
8
|
+
io.path
|
9
|
+
end
|
10
|
+
|
6
11
|
class Token
|
7
12
|
attr_accessor :value, :lineno, :filename
|
8
13
|
|
9
|
-
def initialize
|
14
|
+
def initialize(value, lineno = nil, filename = nil)
|
10
15
|
@value = value
|
11
16
|
@lineno = lineno
|
12
17
|
@filename = filename
|
@@ -33,23 +38,7 @@ module Depager
|
|
33
38
|
class Parser
|
34
39
|
ACC = 0x03ffffff
|
35
40
|
|
36
|
-
|
37
|
-
attr_reader :goto_table, :reduce_table
|
38
|
-
attr_reader :int_to_term, :term_to_int, :nonterm_to_int, :int_to_nonterm
|
39
|
-
|
40
|
-
def initialize
|
41
|
-
@reduce_table,
|
42
|
-
@action_table,
|
43
|
-
@defred_table,
|
44
|
-
@defred_after_shift_table,
|
45
|
-
@goto_table,
|
46
|
-
@term_to_int,
|
47
|
-
@int_to_term,
|
48
|
-
@nonterm_to_int,
|
49
|
-
@int_to_nonterm = basis.class::Tables
|
50
|
-
end
|
51
|
-
|
52
|
-
def parse f, line = ''
|
41
|
+
def parse(f, line = "")
|
53
42
|
basis.__send__ :internal_initialize, f, line, [0, nil]
|
54
43
|
|
55
44
|
do_hook :before_parse
|
@@ -62,52 +51,42 @@ module Depager
|
|
62
51
|
stack[1][2..basis.parser_size]
|
63
52
|
end
|
64
53
|
|
65
|
-
def
|
66
|
-
end
|
54
|
+
def lex; end
|
55
|
+
def accept; end
|
56
|
+
def error; end
|
57
|
+
def shift; end
|
58
|
+
def reduce; end
|
67
59
|
|
68
|
-
def
|
69
|
-
end
|
70
|
-
|
71
|
-
def
|
72
|
-
end
|
73
|
-
|
74
|
-
def
|
75
|
-
end
|
76
|
-
|
77
|
-
def stack
|
78
|
-
basis.stack
|
79
|
-
end
|
80
|
-
|
81
|
-
def lookahead
|
82
|
-
basis.lookahead
|
83
|
-
end
|
84
|
-
|
85
|
-
def action_value
|
86
|
-
basis.action_value
|
87
|
-
end
|
60
|
+
def reduce_table; end
|
61
|
+
def action_table; end
|
62
|
+
def defred_table; end
|
63
|
+
def defred_after_shift_table; end
|
64
|
+
def goto_table; end
|
65
|
+
def term_to_int; end
|
66
|
+
def int_to_term; end
|
67
|
+
def nonterm_to_int; end
|
68
|
+
def int_to_nonterm; end
|
88
69
|
|
89
70
|
protected
|
90
|
-
def lex &block
|
91
|
-
basis.lex &block
|
92
|
-
end
|
93
71
|
|
94
72
|
def driver
|
95
|
-
|
73
|
+
loop do
|
96
74
|
basis.action_value = action_table[stack.last][lookahead[0]] || defred_table[stack.last]
|
97
75
|
|
98
|
-
if action_value
|
76
|
+
if action_value.nil?
|
99
77
|
error
|
100
|
-
|
78
|
+
basis.do_abort_driver
|
101
79
|
elsif action_value == ACC
|
102
|
-
if int_to_term[lookahead[0]]
|
80
|
+
if int_to_term[lookahead[0]].nil?
|
103
81
|
accept
|
82
|
+
return true
|
104
83
|
else
|
105
84
|
error
|
85
|
+
basis.do_abort_driver
|
106
86
|
end
|
107
|
-
return true
|
108
87
|
elsif action_value > 0
|
109
88
|
shift
|
110
|
-
while v = defred_after_shift_table[stack.last]
|
89
|
+
while (v = defred_after_shift_table[stack.last])
|
111
90
|
basis.action_value = v
|
112
91
|
reduce
|
113
92
|
end
|
@@ -118,10 +97,10 @@ module Depager
|
|
118
97
|
end
|
119
98
|
end
|
120
99
|
|
121
|
-
def do_hook
|
100
|
+
def do_hook(hook)
|
122
101
|
if @basis == self
|
123
102
|
send hook
|
124
|
-
elsif hook.to_s
|
103
|
+
elsif /^before_/.match?(hook.to_s)
|
125
104
|
send hook
|
126
105
|
@inside.do_hook hook
|
127
106
|
else
|
@@ -131,45 +110,47 @@ module Depager
|
|
131
110
|
end
|
132
111
|
|
133
112
|
private
|
134
|
-
def before_parse
|
135
|
-
end
|
136
113
|
|
137
|
-
def
|
138
|
-
end
|
114
|
+
def before_parse; end
|
115
|
+
def after_parse; end
|
139
116
|
end
|
140
117
|
|
141
118
|
class Basis < Parser
|
142
|
-
attr_reader
|
119
|
+
attr_reader :basis, :file, :line, :parser_size
|
143
120
|
attr_accessor :lookahead, :action_value, :stack
|
144
121
|
|
145
122
|
def initialize
|
123
|
+
super
|
124
|
+
|
146
125
|
@basis = self
|
147
126
|
@parser_size = 1
|
148
|
-
super()
|
149
127
|
end
|
150
128
|
|
151
129
|
def banner
|
152
130
|
self.class.name
|
153
131
|
end
|
154
132
|
|
155
|
-
def
|
133
|
+
def next_decorator_index
|
156
134
|
@parser_size += 1
|
157
135
|
end
|
158
136
|
|
159
|
-
def accept
|
160
|
-
end
|
137
|
+
def accept; end
|
161
138
|
|
162
139
|
def error
|
163
|
-
path =
|
140
|
+
path = Depager.path_of(file)
|
164
141
|
exp = []
|
165
142
|
action_table[stack.last].each_with_index do |i, x|
|
166
143
|
exp << int_to_term[x] if i
|
167
144
|
end
|
168
|
-
la
|
145
|
+
la = begin
|
146
|
+
lookahead[1].value
|
147
|
+
rescue StandardError
|
148
|
+
lookahead[1]
|
149
|
+
end
|
169
150
|
la = (int_to_term[lookahead[0]] || la).inspect
|
170
|
-
exp = exp.map{|i| i ? i.inspect :
|
151
|
+
exp = exp.map { |i| i ? i.inspect : "$" }.join(", ")
|
171
152
|
warn "#{path}:#{file.lineno}: syntax error(#{banner}), unexpected #{la}, expecting #{exp}."
|
172
|
-
warn @stack.pretty_inspect if Depager.debug_mode?
|
153
|
+
warn @stack.pretty_inspect if Depager.respond_to?(:debug_mode?) && Depager.debug_mode?
|
173
154
|
end
|
174
155
|
|
175
156
|
def shift
|
@@ -178,31 +159,50 @@ module Depager
|
|
178
159
|
|
179
160
|
def reduce
|
180
161
|
r, x = reduce_table[-action_value]
|
181
|
-
(x * 2).times{ stack.pop }
|
162
|
+
(x * 2).times { stack.pop }
|
182
163
|
v = goto_table[stack.last][r]
|
183
164
|
stack << [r, :NT] << v
|
184
165
|
end
|
185
166
|
|
167
|
+
def do_abort_driver
|
168
|
+
abort_driver
|
169
|
+
end
|
170
|
+
|
171
|
+
def abort_driver
|
172
|
+
exit 1
|
173
|
+
end
|
174
|
+
|
186
175
|
private
|
187
|
-
|
188
|
-
|
189
|
-
|
176
|
+
|
177
|
+
def internal_initialize(file, line, lookahead)
|
178
|
+
@stack = [0]
|
179
|
+
@action_value = nil
|
180
|
+
@file = file
|
181
|
+
@line = line
|
182
|
+
@lookahead = lookahead
|
190
183
|
end
|
191
184
|
|
192
|
-
def token
|
185
|
+
def token(sym, value = nil, lineno = nil)
|
193
186
|
lineno ||= file.lineno
|
194
|
-
path = file.respond_to?(:path) ? file.path :
|
195
|
-
|
187
|
+
path = file.respond_to?(:path) ? file.path : "-"
|
188
|
+
[sym, Depager::Token.new(value, lineno, path)]
|
196
189
|
end
|
197
190
|
end
|
198
191
|
|
199
192
|
class AdvancedParser < Parser
|
193
|
+
extend Forwardable
|
194
|
+
delegate %i[
|
195
|
+
lookahead action_value stack lex abort_driver
|
196
|
+
reduce_table action_table defred_table defred_after_shift_table goto_table
|
197
|
+
term_to_int int_to_term nonterm_to_int int_to_nonterm
|
198
|
+
] => :@basis
|
199
|
+
|
200
200
|
attr_reader :basis, :decorator_index
|
201
201
|
|
202
|
-
def initialize
|
202
|
+
def initialize(inside)
|
203
203
|
@inside = inside
|
204
204
|
@basis = inside.basis
|
205
|
-
@decorator_index = @basis.
|
205
|
+
@decorator_index = @basis.next_decorator_index
|
206
206
|
super()
|
207
207
|
end
|
208
208
|
|
@@ -231,49 +231,36 @@ module Depager
|
|
231
231
|
end
|
232
232
|
|
233
233
|
private
|
234
|
-
def before_accept
|
235
|
-
end
|
236
234
|
|
237
|
-
def
|
238
|
-
end
|
239
|
-
|
240
|
-
def
|
241
|
-
end
|
242
|
-
|
243
|
-
def
|
244
|
-
end
|
245
|
-
|
246
|
-
def before_shift
|
247
|
-
end
|
248
|
-
|
249
|
-
def after_shift
|
250
|
-
end
|
251
|
-
|
252
|
-
def before_reduce
|
253
|
-
end
|
254
|
-
|
255
|
-
def after_reduce
|
256
|
-
end
|
235
|
+
def before_accept; end
|
236
|
+
def after_accept; end
|
237
|
+
def before_error; end
|
238
|
+
def after_error; end
|
239
|
+
def before_shift; end
|
240
|
+
def after_shift; end
|
241
|
+
def before_reduce; end
|
242
|
+
def after_reduce; end
|
257
243
|
end
|
258
244
|
|
259
245
|
class Action < AdvancedParser
|
260
|
-
def
|
261
|
-
|
246
|
+
def on_reduce; end
|
247
|
+
|
248
|
+
def initialize(inside)
|
249
|
+
super
|
262
250
|
@_arguments = []
|
263
|
-
@on_reduce, = self.class::Tables
|
264
251
|
end
|
265
252
|
|
266
253
|
def before_reduce
|
267
254
|
@_arguments = []
|
268
255
|
n = reduce_table[-action_value][1]
|
269
256
|
n.times do |i|
|
270
|
-
v = stack[stack.size - 2 * (i + 1)]
|
257
|
+
v = stack[stack.size - (2 * (i + 1))]
|
271
258
|
@_arguments[n - i - 1] = v[1] == :NT ? v[decorator_index] : v[1]
|
272
259
|
end
|
273
260
|
end
|
274
261
|
|
275
262
|
def after_reduce
|
276
|
-
method =
|
263
|
+
method = on_reduce[-action_value]
|
277
264
|
result = method ? send(method, @_arguments) : nil
|
278
265
|
stack[stack.size - 2][decorator_index] = result
|
279
266
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class Depager::RieExtension
|
2
|
+
module DebugHelper
|
3
|
+
def inspect
|
4
|
+
"<#{node_name}:#{node_values.inspect}>"
|
5
|
+
end
|
6
|
+
|
7
|
+
def pretty_print(q)
|
8
|
+
q.group(1, "<#{node_name}:", ">") { q.pp node_values }
|
9
|
+
end
|
10
|
+
|
11
|
+
def node_name
|
12
|
+
self.class.name.split("::").last
|
13
|
+
end
|
14
|
+
|
15
|
+
def node_values
|
16
|
+
to_h.tap { _1.delete(:lineno) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Nodes
|
21
|
+
N_THREAD.class_eval do
|
22
|
+
include DebugHelper
|
23
|
+
end
|
24
|
+
|
25
|
+
N_TRANSFER.class_eval do
|
26
|
+
include DebugHelper
|
27
|
+
end
|
28
|
+
|
29
|
+
N_EXCEPT.class_eval do
|
30
|
+
include DebugHelper
|
31
|
+
end
|
32
|
+
|
33
|
+
N_LET.class_eval do
|
34
|
+
include DebugHelper
|
35
|
+
end
|
36
|
+
|
37
|
+
N_ACTION.class_eval do
|
38
|
+
include DebugHelper
|
39
|
+
end
|
40
|
+
|
41
|
+
N_ATOC.class_eval do
|
42
|
+
include DebugHelper
|
43
|
+
|
44
|
+
def inspect
|
45
|
+
name = sym_name == "$" ? "$#{grammar.symname(grammar[rx].lhs)}" : sym_name
|
46
|
+
"<N_ATOC:#{[name, attr_name, rx].inspect}>"
|
47
|
+
end
|
48
|
+
|
49
|
+
def pretty_print(q)
|
50
|
+
name = begin
|
51
|
+
sym_name == "$" ? "$#{grammar.symname(grammar[rx].lhs)}" : sym_name
|
52
|
+
rescue StandardError
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
q.group(1, "<N_ATOC:", ">") { q.pp [name, attr_name, rx] }
|
56
|
+
end
|
57
|
+
|
58
|
+
def grammar
|
59
|
+
$grammar # rubocop: disable Style/GlobalVars
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Depager::ActionExtension < Depager::Extension
|
2
|
+
def init_extension
|
3
|
+
@action_code = ""
|
4
|
+
@on_reduce = []
|
5
|
+
end
|
6
|
+
|
7
|
+
def term_extension
|
8
|
+
g_parser.outer_code <<
|
9
|
+
generate_action_decorator_code(@on_reduce, @action_code)
|
10
|
+
end
|
11
|
+
|
12
|
+
def pre_rule_list
|
13
|
+
return unless /^%ACTION\{\s*$/.match?(g_parser.original_line)
|
14
|
+
|
15
|
+
while (line = file.gets)
|
16
|
+
break if /^%\}\s*$/.match?(line)
|
17
|
+
|
18
|
+
@action_code << line
|
19
|
+
end
|
20
|
+
g_parser.update_context ""
|
21
|
+
end
|
22
|
+
|
23
|
+
def post_rhs
|
24
|
+
return unless /\s*\{/.match?(g_parser.line)
|
25
|
+
|
26
|
+
@original_line = g_parser.original_line
|
27
|
+
@line = g_parser.line
|
28
|
+
lineno = g_parser.file.lineno
|
29
|
+
code = modify_action_code(parse_block)
|
30
|
+
n = g_parser.rules.size - 1
|
31
|
+
@action_code <<
|
32
|
+
expand_inline_code(code, lineno, wrap: "def _act_#{n} val", delta: 1)
|
33
|
+
g_parser.update_context @line
|
34
|
+
@on_reduce[n] = ":_act_#{n}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def modify_action_code(code)
|
38
|
+
let_code = " # empty rule\n"
|
39
|
+
unless g_parser.rhs_names.empty?
|
40
|
+
vars = g_parser.rhs_names.map do |i|
|
41
|
+
/[a-zA-Z][a-zA-Z0-9_]*/.match?(i) ? "_#{i}" : "_"
|
42
|
+
end
|
43
|
+
let_code = " #{vars.join(', ')}, = *val\n"
|
44
|
+
end
|
45
|
+
let_code << code
|
46
|
+
end
|
47
|
+
end
|
@@ -1,9 +1,8 @@
|
|
1
1
|
%defext Depager::ASTBuilderExtension
|
2
|
-
%extend Depager::Lexer ('plugins/lex.rb')
|
3
|
-
%extend Depager::Action ('plugins/action.rb')
|
2
|
+
%extend Depager::Lexer ('depager/plugins/lex.rb')
|
3
|
+
%extend Depager::Action ('depager/plugins/action.rb')
|
4
4
|
%decorate @Action
|
5
|
-
#%decorate Depager::LALR::ShiftReducePrinter ('plugins/srp.rb')
|
6
|
-
%expanded_code_delimiter DEPAGER_EXPANDED_CODE
|
5
|
+
#%decorate Depager::LALR::ShiftReducePrinter ('depager/plugins/srp.rb')
|
7
6
|
%inner{
|
8
7
|
attr_accessor :action_code, :on_reduce, :visitors
|
9
8
|
def init_extension
|
@@ -19,11 +18,11 @@
|
|
19
18
|
|
20
19
|
def modify_action_code code, nodes=[]
|
21
20
|
code = code.gsub(/\$\.([a-z_])/, 'node.\1')
|
22
|
-
code <<
|
21
|
+
code << <<-CODE
|
23
22
|
rescue
|
24
23
|
warn "raise at src:\#{node.lineno}/\#{node.class.name}"
|
25
24
|
raise
|
26
|
-
|
25
|
+
CODE
|
27
26
|
end
|
28
27
|
|
29
28
|
def gen_accept_code sym
|
@@ -80,11 +79,11 @@
|
|
80
79
|
{ "" }
|
81
80
|
| NODE opt_attr ACTION
|
82
81
|
{
|
83
|
-
ini =
|
82
|
+
ini = <<-CODE
|
84
83
|
def initialize
|
85
84
|
#{_ACTION.value}
|
86
85
|
end
|
87
|
-
|
86
|
+
CODE
|
88
87
|
ERB.new(master.class::BASE_NODE_TEMPLATE, nil, '-').result(binding)
|
89
88
|
}
|
90
89
|
;
|
@@ -173,11 +172,11 @@
|
|
173
172
|
%inner{
|
174
173
|
def do_default
|
175
174
|
n = g_parser.rules.size-1
|
176
|
-
master.action_code <<
|
175
|
+
master.action_code << <<~CODE
|
177
176
|
def _ast_#{n} val
|
178
177
|
NilNode.new(basis.file.lineno)
|
179
178
|
end
|
180
|
-
|
179
|
+
CODE
|
181
180
|
master.on_reduce[n] = ":_ast_#{n}"
|
182
181
|
end
|
183
182
|
%}
|
@@ -266,7 +265,7 @@
|
|
266
265
|
%%
|
267
266
|
|
268
267
|
class Depager::ASTBuilderExtension
|
269
|
-
BASE_NODE_TEMPLATE = <<-'
|
268
|
+
BASE_NODE_TEMPLATE = <<-'CODE'
|
270
269
|
class Node
|
271
270
|
attr_accessor :lineno
|
272
271
|
attr_accessor <%= _opt_attr.map{|i| ":#{i}" }.join(', ') %>
|
@@ -331,14 +330,14 @@ class Depager::ASTBuilderExtension
|
|
331
330
|
def accept v
|
332
331
|
end
|
333
332
|
end
|
334
|
-
|
333
|
+
CODE
|
335
334
|
|
336
|
-
NODE_TEMPLATE = <<-'
|
335
|
+
NODE_TEMPLATE = <<-'CODE'
|
337
336
|
class Node_<%= name %> < Node
|
338
337
|
attr_accessor <%= nodes.map{|i| ":#{i}" }.join(', ') %>
|
339
338
|
attr_accessor <%= attrs.map{|i| ":#{i}" }.join(', ') %>
|
340
339
|
|
341
|
-
def initialize <%=
|
340
|
+
def initialize <%= ['lineno', *nodes].join(', ') %>
|
342
341
|
super()
|
343
342
|
@lineno = lineno
|
344
343
|
<%= nodes.inject(''){|r,i| r << " @#{i} = #{i}\n"} %>
|
@@ -350,15 +349,19 @@ class Depager::ASTBuilderExtension
|
|
350
349
|
v.visit_Node_<%= name %>(self)
|
351
350
|
self
|
352
351
|
end
|
352
|
+
|
353
|
+
def attributes
|
354
|
+
{ <%= (nodes + attrs).uniq.map{|i| "#{i}: #{i}" }.join(', ') %>, lineno: lineno }
|
355
|
+
end
|
353
356
|
end
|
354
|
-
|
357
|
+
CODE
|
355
358
|
|
356
|
-
VISITOR_TEMPLATE = <<-'
|
359
|
+
VISITOR_TEMPLATE = <<-'CODE'
|
357
360
|
class Visitor<%= name ? '_' + name : '' %>
|
358
361
|
def visit node
|
359
362
|
node.accept(self)
|
360
363
|
end
|
361
364
|
<%= body.join %>
|
362
365
|
end # Visitor<%= name ? '_' + name : '' %>
|
363
|
-
|
366
|
+
CODE
|
364
367
|
end
|