depager 0.2.3 → 0.3.0.b20160729
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.en +4 -19
- data/README.ja +42 -79
- data/bin/depager +42 -45
- data/examples/action_pl0d/pl0d.action.dr +421 -0
- data/examples/action_pl0d/test.pl0ds +49 -0
- data/examples/c89/c89.dr +493 -496
- data/examples/c89/test.c89 +10 -10
- data/examples/extension/astdf.rb +10 -0
- data/examples/extension/atree.dr +55 -0
- data/examples/{sample_calc → extension}/calc.atree.dr +42 -43
- data/examples/extension/calc.simple_action.dr +33 -0
- data/examples/extension/paction.dr +16 -15
- data/examples/extension/pactiontest.dr +14 -14
- data/examples/extension/simple_action.rb +44 -0
- data/examples/pl0d/pl0ds.dr +337 -334
- data/examples/pl0d/test.pl0ds +33 -33
- data/examples/rie_calc/calc.rie.dr +57 -0
- data/examples/rie_calc/test.calc +4 -0
- data/examples/rie_dcuse/dcuse.rie.dr +71 -0
- data/examples/rie_dcuse/test.dcuse +1 -0
- data/examples/rie_pl0/orig_ex/exerrdg.pl0 +44 -0
- data/examples/rie_pl0/orig_ex/exerrm.pl0 +19 -0
- data/examples/rie_pl0/orig_ex/exerrmre.pl0 +20 -0
- data/examples/rie_pl0/orig_ex/exerrtok.pl0 +18 -0
- data/examples/rie_pl0/orig_ex/exmdg.pl0 +40 -0
- data/examples/rie_pl0/orig_ex/exmdgwwl.pl0 +43 -0
- data/examples/rie_pl0/orig_ex/exmrw.pl0 +22 -0
- data/examples/rie_pl0/orig_ex/exmwwl.pl0 +18 -0
- data/examples/rie_pl0/orig_ex/exnorw.pl0 +17 -0
- data/examples/rie_pl0/pl0.rie.dr +450 -0
- data/examples/rie_pl0/test.pl0 +10 -0
- data/examples/sample_calc/calc.action.dr +33 -33
- data/examples/sample_calc/calc.ast.action.dr +65 -66
- data/examples/sample_calc/calc.ast.dr +55 -55
- data/examples/sample_calc/calc.cst.dr +45 -45
- data/examples/sample_calc/calc.dr +43 -43
- data/examples/sample_calc/calc.lex.dr +29 -29
- data/examples/sample_calc/{calc_prec.nvaction.dr → calc_prec.action.dr} +31 -31
- data/examples/slex_test/divreg.slex.dr +29 -29
- data/examples/slex_test/ljoin.slex.dr +36 -36
- data/examples/slex_test/test.divreg +1 -1
- data/examples/slex_test/test.ljoin +3 -3
- data/lib/depager.rb +582 -670
- data/lib/depager/grammar.rb +256 -291
- data/lib/depager/lr.rb +574 -579
- data/lib/depager/parser.rb +282 -277
- data/lib/depager/ruby/plugins/_rie_debug.rb +35 -0
- data/lib/depager/ruby/plugins/action.rb +53 -43
- data/lib/depager/ruby/plugins/ast.dr +364 -269
- data/lib/depager/ruby/plugins/ast.rb +1367 -1308
- data/lib/depager/ruby/plugins/cst.dr +172 -180
- data/lib/depager/ruby/plugins/cst.rb +587 -626
- data/lib/depager/ruby/plugins/lex.dr +85 -89
- data/lib/depager/ruby/plugins/lex.rb +310 -336
- data/lib/depager/ruby/plugins/rie.dr +723 -0
- data/lib/depager/ruby/plugins/rie.rb +1653 -0
- data/lib/depager/ruby/plugins/slex.dr +202 -200
- data/lib/depager/ruby/plugins/slex.rb +780 -817
- data/lib/depager/ruby/plugins/srp.rb +56 -51
- data/lib/depager/ruby/templates/extension_lalr_master.erb +46 -51
- data/lib/depager/ruby/templates/extension_lalr_slave.erb +99 -107
- data/lib/depager/ruby/templates/single_lalr_parser.erb +115 -117
- data/lib/depager/utils.rb +148 -318
- data/lib/depager/version.rb +4 -3
- metadata +52 -60
- data/ChangeLog +0 -16
- data/data/depager/pre-setup.rb +0 -3
- data/examples/c89/c89.tab.rb +0 -7127
- data/examples/pl0d/pl0ds.tab.rb +0 -2698
- data/examples/sample_calc/calc.action.tab.rb +0 -457
- data/examples/sample_calc/calc.ast.action.tab.rb +0 -749
- data/examples/sample_calc/calc.ast.tab.rb +0 -665
- data/examples/sample_calc/calc.astdf.dr +0 -54
- data/examples/sample_calc/calc.astdf.tab.rb +0 -672
- data/examples/sample_calc/calc.atree.tab.rb +0 -451
- data/examples/sample_calc/calc.cst.tab.rb +0 -644
- data/examples/sample_calc/calc.lex.tab.rb +0 -374
- data/examples/sample_calc/calc.nvaction.dr +0 -33
- data/examples/sample_calc/calc.nvaction.tab.rb +0 -465
- data/examples/sample_calc/calc.tab.rb +0 -365
- data/examples/sample_calc/calc_prec.nvaction.tab.rb +0 -431
- data/examples/slex_test/divreg.slex.tab.rb +0 -303
- data/examples/slex_test/ljoin.slex.tab.rb +0 -370
- data/lib/depager/ruby/plugins/_ast_tmpl.rb +0 -73
- data/lib/depager/ruby/plugins/astdf.rb +0 -6
- data/lib/depager/ruby/plugins/atree.dr +0 -55
- data/lib/depager/ruby/plugins/atree.rb +0 -347
- data/lib/depager/ruby/plugins/nvaction.rb +0 -19
- data/lib/depager/ruby/templates/simple.erb +0 -23
- data/setup.rb +0 -1585
@@ -0,0 +1,723 @@
|
|
1
|
+
%defext Depager::RieExtension
|
2
|
+
%extend Depager::Lexer ('plugins/lex.rb')
|
3
|
+
%extend Depager::Action ('plugins/action.rb')
|
4
|
+
%decorate @Action
|
5
|
+
#%decorate Depager::LALR::ShiftReducePrinter ('plugins/srp.rb')
|
6
|
+
%expanded_code_delimiter DEPAGER_EXPANDED_CODE
|
7
|
+
%inner{
|
8
|
+
module Nodes
|
9
|
+
N_THREAD = Struct.new :lineno, :targets, :excepts
|
10
|
+
N_TRANSFER = Struct.new :lineno, :targets, :excepts
|
11
|
+
N_EXCEPT = Struct.new :lineno, :let_or_ids
|
12
|
+
N_LET = Struct.new :lineno, :atoc, :expr, :state
|
13
|
+
N_ACTION = Struct.new :lineno, :expr
|
14
|
+
N_ATOC = Struct.new :lineno, :sym_name, :attr_name, :rx
|
15
|
+
end
|
16
|
+
include Nodes
|
17
|
+
|
18
|
+
begin
|
19
|
+
Depager.debug_mode? and require 'plugins/_rie_debug.rb'
|
20
|
+
rescue LoadError
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_accessor :action_code, :on_reduce, :semantics, :attributes, :ecs
|
24
|
+
attr_reader :grammar
|
25
|
+
|
26
|
+
def init_extension
|
27
|
+
@action_code = ''
|
28
|
+
@on_reduce = []
|
29
|
+
@on_state = []
|
30
|
+
@attributes = []
|
31
|
+
@semantics = [[]]
|
32
|
+
@locals = [{}]
|
33
|
+
@ecs = {}
|
34
|
+
if Depager.debug_mode?
|
35
|
+
@debug_output_path = "#{g_parser.file.path}.rie_debug.output"
|
36
|
+
File.unlink @debug_output_path rescue nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def term_extension
|
41
|
+
$grammar = @grammar = g_parser.table.grammar
|
42
|
+
expand_short_hand_notation
|
43
|
+
error_exit_if_error_pending
|
44
|
+
|
45
|
+
check_lattr
|
46
|
+
error_exit_if_error_pending
|
47
|
+
debug_info "locals:\n#{@locals.pretty_inspect}"
|
48
|
+
|
49
|
+
generate_action
|
50
|
+
g_parser.outer_code << generate_rie_decorator_code(@on_reduce, @on_state, @action_code)
|
51
|
+
end
|
52
|
+
|
53
|
+
def expand_short_hand_notation
|
54
|
+
semantics = []
|
55
|
+
@semantics.each_with_index do |rule_semantics, x|
|
56
|
+
res = []
|
57
|
+
(rule_semantics || []).each do |semantic|
|
58
|
+
case semantic
|
59
|
+
when N_TRANSFER ; expand_transfer res, semantic, grammar[x]
|
60
|
+
when N_THREAD ; expand_thread res, semantic, grammar[x]
|
61
|
+
else res << semantic
|
62
|
+
end
|
63
|
+
end
|
64
|
+
semantics << res
|
65
|
+
end
|
66
|
+
@semantics = semantics
|
67
|
+
end
|
68
|
+
|
69
|
+
def expand_transfer res, transfer, rule
|
70
|
+
lineno = transfer.lineno
|
71
|
+
transfer.targets.each do |attr_name|
|
72
|
+
unless @attributes[rule.lhs].include?(attr_name)
|
73
|
+
pending_error "#{attr_name} is not lhs attribute.", lineno
|
74
|
+
next
|
75
|
+
end
|
76
|
+
used = false
|
77
|
+
rule.rhs.each_with_index do |rsym, i|
|
78
|
+
next unless grammar.nonterm? rsym
|
79
|
+
|
80
|
+
rname = rule.rhs_names[i]
|
81
|
+
rattrs = @attributes[rsym] || []
|
82
|
+
next if !rattrs.include?(attr_name) || transfer.excepts.find do |e|
|
83
|
+
rname == e.sym_name and rattrs.include?(e.attr_name)
|
84
|
+
end
|
85
|
+
if attr_name[0] == ?_ # inherited attr
|
86
|
+
res << N_LET[lineno, N_ATOC[lineno, rname, attr_name, rule.n],
|
87
|
+
[N_ATOC[lineno, '$', attr_name, rule.n]]]
|
88
|
+
used = true
|
89
|
+
else
|
90
|
+
if used
|
91
|
+
pending_error "transfer `$.#{attr_name}' has too many source."
|
92
|
+
break
|
93
|
+
end
|
94
|
+
res << N_LET[lineno, N_ATOC[lineno, '$', attr_name, rule.n],
|
95
|
+
[N_ATOC[lineno, rname, attr_name, rule.n]]]
|
96
|
+
used = true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
unless used
|
100
|
+
pending_error "no rhs symbol have attribute `#{attr_name}'", lineno
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def expand_thread res, thread, rule
|
106
|
+
lineno, excepts = thread.lineno, thread.excepts.dup
|
107
|
+
thread.targets.each do |syn_name|
|
108
|
+
inh_name = '_' + syn_name
|
109
|
+
from, used = nil, false
|
110
|
+
|
111
|
+
lname = rule.lhs_name
|
112
|
+
lattrs = @attributes[rule.lhs]
|
113
|
+
|
114
|
+
if lattrs.include?(inh_name)
|
115
|
+
from = N_ATOC[lineno, '$', inh_name, rule.n]
|
116
|
+
end
|
117
|
+
rule.rhs.each_with_index do |rsym, i|
|
118
|
+
rname = rule.rhs_names[i]
|
119
|
+
rattrs = @attributes[rsym] || []
|
120
|
+
|
121
|
+
if from and rattrs.include? inh_name and
|
122
|
+
not excepts.find{|e| rname == e.sym_name && rattrs.include?(e.attr_name) }
|
123
|
+
res << N_LET[lineno, N_ATOC[lineno, rname, inh_name, rule.n], [from]]
|
124
|
+
used = true
|
125
|
+
end
|
126
|
+
if rattrs.include? syn_name
|
127
|
+
from = N_ATOC[lineno, rname, syn_name, rule.n]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
if from and lattrs.include?(syn_name) and
|
131
|
+
not excepts.find{|e| lname == e.sym_name && lattrs.include?(e.attr_name) }
|
132
|
+
res << N_LET[lineno, N_ATOC[lineno, '$', syn_name, rule.n], [from]]
|
133
|
+
used = true
|
134
|
+
end
|
135
|
+
unless used
|
136
|
+
pending_error "no rhs symbol have attribute `#{syn_name}'", lineno
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def check_lattr
|
142
|
+
@inhs_of_nonterms = []
|
143
|
+
@semantics.each_with_index do |rule_semantics, x|
|
144
|
+
rule = grammar[x]
|
145
|
+
assigned = {}
|
146
|
+
locals = @locals[rule.n] = {}
|
147
|
+
rule_semantics.each do |semantic|
|
148
|
+
semantic.is_a? N_LET and check_lattr_let semantic, rule, locals, assigned
|
149
|
+
end
|
150
|
+
|
151
|
+
next if x == 0
|
152
|
+
lineno = rule_semantics.last.lineno rescue 0
|
153
|
+
@attributes[rule.lhs].each do |a|
|
154
|
+
if a[0] != ?_ and not assigned[['$', a]]
|
155
|
+
pending_error "attribute `$.#{a}' is not assigned.", lineno
|
156
|
+
end
|
157
|
+
end
|
158
|
+
rule.rhs.each_with_index do |rsym, y|
|
159
|
+
next unless grammar.nonterm? rsym
|
160
|
+
rname = rule.rhs_names[y]
|
161
|
+
@attributes[rsym].each do |a|
|
162
|
+
if a[0] == ?_ and not assigned[[rname, a]]
|
163
|
+
pending_error "attribute `#{rname}.#{a}' is not assigned.", lineno
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def check_lattr_let let, rule, locals, assigned
|
171
|
+
lineno = let.lineno
|
172
|
+
attr_name = let.atoc.attr_name
|
173
|
+
sym_name = let.atoc.sym_name
|
174
|
+
|
175
|
+
# left hand side of let
|
176
|
+
unless valid_atoc? let.atoc
|
177
|
+
pending_error "invalid attribute occurrence `#{sym_name}.#{attr_name}'.", lineno
|
178
|
+
return
|
179
|
+
end
|
180
|
+
if let.atoc.sym_name == '$' and inh_atoc?(let.atoc)
|
181
|
+
pending_error "cannot assign `$.#{attr_name}'(LHS INH).", lineno
|
182
|
+
return
|
183
|
+
elsif let.atoc.sym_name != '$' and syn_atoc?(let.atoc)
|
184
|
+
pending_error "cannot assign `#{sym_name}.#{attr_name}'(RHS SYN).", lineno
|
185
|
+
return
|
186
|
+
end
|
187
|
+
if local_atoc?(let.atoc)
|
188
|
+
if locals[attr_name]
|
189
|
+
warning "local attributes `#{attr_name}' is reassigned.", lineno
|
190
|
+
end
|
191
|
+
locals[attr_name] = 0
|
192
|
+
else
|
193
|
+
if assigned[[sym_name, attr_name]]
|
194
|
+
warning "attributes `#{sym_name}.#{attr_name}' is reassined.", lineno
|
195
|
+
else
|
196
|
+
assigned[[sym_name, attr_name]] = true
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# right hand side of let
|
201
|
+
let.expr.find_all{|i| i.is_a? N_ATOC }.each do |expr_atoc|
|
202
|
+
unless valid_atoc? expr_atoc
|
203
|
+
next unless valid_atoc_name? expr_atoc # it is not atoc
|
204
|
+
pending_error "invalid attribute occurrence"<<
|
205
|
+
" `#{expr_atoc.sym_name}.#{expr_atoc.attr_name}'.", lineno
|
206
|
+
next
|
207
|
+
end
|
208
|
+
if expr_atoc.sym_name == '$' and syn_atoc?(expr_atoc)
|
209
|
+
pending_error "cannot refer `$.#{expr_atoc.attr_name}'(LHS SYN).", lineno
|
210
|
+
next
|
211
|
+
elsif expr_atoc.sym_name != '$' and inh_atoc?(expr_atoc)
|
212
|
+
pending_error "cannot refer `#{expr_atoc.sym_name}." <<
|
213
|
+
"#{expr_atoc.attr_name}'(RHS INH).", lineno
|
214
|
+
next
|
215
|
+
end
|
216
|
+
if local_atoc?(let.atoc)
|
217
|
+
if local_atoc?(expr_atoc) # local<-local
|
218
|
+
n = locals[expr_atoc.attr_name]
|
219
|
+
elsif syn_atoc?(expr_atoc) # local<-rsym.syn
|
220
|
+
n = rhs_index(expr_atoc)+1
|
221
|
+
else # local<-$.inh
|
222
|
+
n = 0
|
223
|
+
end
|
224
|
+
locals[attr_name] = n if locals[attr_name] < n
|
225
|
+
elsif sym_name != '$' and local_atoc?(expr_atoc) and # rhs<-local
|
226
|
+
rhs_index(let.atoc) <= locals[expr_atoc.attr_name]
|
227
|
+
pending_error "L-attribute violation.", lineno
|
228
|
+
next
|
229
|
+
elsif sym_name != '$' and expr_atoc.sym_name != '$' and # rhs<-rhs
|
230
|
+
rhs_index(let.atoc) <= rhs_index(expr_atoc)
|
231
|
+
pending_error "L-attribute violation.", lineno
|
232
|
+
next
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def generate_action
|
238
|
+
# Actions on state change.
|
239
|
+
g_parser.table.states.each_with_index do |state, x|
|
240
|
+
actions = [ ]
|
241
|
+
inhs, locals = check_state_uniqueness(state)
|
242
|
+
inhs.each do |key, exprs| ; sym, attr_name = key
|
243
|
+
atoc = N_ATOC[0, "%#{sym}", attr_name]
|
244
|
+
actions << node_to_code(N_LET[0, atoc, exprs], state)
|
245
|
+
end
|
246
|
+
locals.each do |rx, attr_name, exprs|
|
247
|
+
atoc = N_ATOC[0, nil, attr_name, rx]
|
248
|
+
actions << node_to_code(N_LET[0, atoc, exprs], state)
|
249
|
+
end
|
250
|
+
unless actions.empty?
|
251
|
+
@action_code << "def _rie_state_#{x}\n #{actions.join("\n ")}\nend\n"
|
252
|
+
@on_state[x] = ":_rie_state_#{x}"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
# Actions on reduce
|
257
|
+
@semantics.each_with_index do |rule_semantics, x|
|
258
|
+
actions = [ ]
|
259
|
+
rule = grammar[x]
|
260
|
+
rule_semantics.each do |semantic|
|
261
|
+
if semantic.is_a?(N_LET)
|
262
|
+
next if inh_atoc?(semantic.atoc)
|
263
|
+
next if local_atoc?(semantic.atoc) and not
|
264
|
+
@locals[x].find{|k,v| k == semantic.atoc.attr_name && v == rule.rhs.size }
|
265
|
+
end
|
266
|
+
code = node_to_code(semantic)
|
267
|
+
actions << code
|
268
|
+
end
|
269
|
+
unless actions.empty?
|
270
|
+
@action_code << "def _rie_reduce_#{x}\n #{actions.join("\n ")}\nend\n"
|
271
|
+
@on_reduce[x] = ":_rie_reduce_#{x}"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def node_to_code node, state=nil
|
277
|
+
case node
|
278
|
+
when N_LET
|
279
|
+
node_to_code(node.atoc, state) +" = "+
|
280
|
+
node_to_code(N_ACTION[0, node.expr], state)
|
281
|
+
when N_ACTION
|
282
|
+
node.expr.inject('') do |r, i|
|
283
|
+
r << (i.is_a?(N_ATOC) ? node_to_code(i, state) :
|
284
|
+
i.match(/^\s*[\{\[\(]$/) ? i : " #{i}")
|
285
|
+
end
|
286
|
+
when N_ATOC
|
287
|
+
return " #{node.sym_name}.#{node.attr_name}" unless valid_atoc? node
|
288
|
+
dot = 0
|
289
|
+
if state and item = state.closure.find{|i| i.rule.n == node.rx }
|
290
|
+
dot = item.n
|
291
|
+
elsif node.rx
|
292
|
+
dot = grammar[node.rx].rhs.size
|
293
|
+
end
|
294
|
+
if grammar.term? atoc_to_sym(node)
|
295
|
+
x = rhs_index(node) - dot
|
296
|
+
" _sstack(#{x}).syn.#{node.attr_name}"
|
297
|
+
elsif local_atoc? node
|
298
|
+
x = -dot
|
299
|
+
" _sstack(#{x-1}).local['#{node.attr_name}@#{node.rx}']"
|
300
|
+
elsif inh_atoc? node
|
301
|
+
# NEVER ASN LHS($).INH
|
302
|
+
if node.sym_name =~ /^%/ # ASN RHS.INH
|
303
|
+
x, sym = 0, $'
|
304
|
+
else # REF LHS($).INH / RHS.INH
|
305
|
+
x, sym = (rhs_index(node) || 0) - dot, atoc_to_sym(node)
|
306
|
+
end
|
307
|
+
ec = @ecs[[sym, node.attr_name]]
|
308
|
+
" _sstack(#{x-1}).inh['#{ec || sym}.#{node.attr_name}']"
|
309
|
+
else # syn_atoc?
|
310
|
+
# NEVER ASN RHS.SYN
|
311
|
+
if node.sym_name == '$' # ASN/REF LHS($).SYN
|
312
|
+
" @_rie_reduce_syn['#{node.attr_name}']"
|
313
|
+
else # REF RHS.SYN
|
314
|
+
x = rhs_index(node) - dot
|
315
|
+
" _sstack(#{x}).syn['#{node.attr_name}']"
|
316
|
+
end
|
317
|
+
end
|
318
|
+
else ; raise "cannot happen(#{node.inspect})."
|
319
|
+
end
|
320
|
+
rescue ; warn node.pretty_inspect ; raise
|
321
|
+
end
|
322
|
+
|
323
|
+
def check_state_uniqueness state
|
324
|
+
inhs, ec_inhs, locals = {}, {}, []
|
325
|
+
state.closure.each do |item|
|
326
|
+
rule = item.rule
|
327
|
+
@semantics[rule.n].each do |let|
|
328
|
+
next if !let.is_a?(N_LET)
|
329
|
+
next if item.n == rule.rhs.size
|
330
|
+
if local_atoc?(let.atoc)
|
331
|
+
@locals[rule.n].find{|k, v| k == let.atoc.attr_name && v == item.n } and
|
332
|
+
locals << [rule.n, let.atoc.attr_name, let.expr]
|
333
|
+
next
|
334
|
+
end
|
335
|
+
next if syn_atoc?(let.atoc) or rhs_index(let.atoc) != item.n
|
336
|
+
|
337
|
+
# ok, atoc is A._inh(B -> alpa _ A beta). set E_state(atoc).
|
338
|
+
attr_name = let.atoc.attr_name
|
339
|
+
sym = atoc_to_sym(let.atoc)
|
340
|
+
key = [sym, attr_name]
|
341
|
+
if expr = inhs[key]
|
342
|
+
if expr.size == 1 and expr[0].is_a?(N_ATOC) and
|
343
|
+
atoc_to_sym(expr[0]) == sym and expr[0].attr_name == attr_name
|
344
|
+
# older is self copy, update it.
|
345
|
+
inhs.delete(key)
|
346
|
+
inhs[key] = replace_atoc expr, inhs
|
347
|
+
elsif let.expr.size == 1 and let.expr[0].is_a?(N_ATOC) and
|
348
|
+
atoc_to_sym(let.expr[0]) == sym and let.expr[0].attr_name == attr_name
|
349
|
+
# newer is self copy, skip.
|
350
|
+
elsif not same_semantic? expr, let.expr
|
351
|
+
error_exit "LALR-attribute violation."
|
352
|
+
end
|
353
|
+
else
|
354
|
+
inhs[key] = replace_atoc let.expr, inhs
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
# check eclr
|
360
|
+
inhs.each do |k, v|
|
361
|
+
sym, attr_name = k
|
362
|
+
if ec = @ecs[k]
|
363
|
+
key = [ec, attr_name]
|
364
|
+
if ec_inhs[key]
|
365
|
+
unless same_semantic? ec_inhs[key], v
|
366
|
+
error_exit "ECLR-attribute violation."
|
367
|
+
end
|
368
|
+
else
|
369
|
+
ec_inhs[key] = v
|
370
|
+
end
|
371
|
+
else
|
372
|
+
ec_inhs[k] = v
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
debug_info "\n----------\n#{state}"
|
377
|
+
ec_inhs.each{|k,v| s,a=k;debug_info "#{grammar.symname s}:#{s}.#{a}=>#{v.pretty_inspect}" }
|
378
|
+
locals.each{|x,k,v| debug_info "#{x}.#{k}=>#{v.pretty_inspect}"}
|
379
|
+
return ec_inhs, locals
|
380
|
+
end
|
381
|
+
|
382
|
+
def same_semantic? sa, sb
|
383
|
+
return false unless sa.size == sb.size
|
384
|
+
sa.size.times do |x| a, b = sa[x], sb[x]
|
385
|
+
return false unless a.class == b.class
|
386
|
+
if a.is_a? N_ATOC
|
387
|
+
asym = a.sym_name == '$' ? atoc_to_sym(a) : a.sym_name
|
388
|
+
bsym = b.sym_name == '$' ? atoc_to_sym(b) : b.sym_name
|
389
|
+
asym = @ecs[[asym, a.attr_name]] if @ecs[[asym, a.attr_name]]
|
390
|
+
bsym = @ecs[[bsym, b.attr_name]] if @ecs[[bsym, b.attr_name]]
|
391
|
+
return false unless asym == bsym && a.attr_name == b.attr_name
|
392
|
+
else
|
393
|
+
return false unless a == b
|
394
|
+
end
|
395
|
+
end
|
396
|
+
return true
|
397
|
+
end
|
398
|
+
|
399
|
+
def replace_atoc expr, inhs={}
|
400
|
+
# warn "REPLACE:#{expr.pretty_inspect}"
|
401
|
+
res = []
|
402
|
+
expr and expr.each do |node|
|
403
|
+
if node.is_a? N_ATOC
|
404
|
+
if replace_to = inhs[[atoc_to_sym(node), node.attr_name]]
|
405
|
+
res.concat replace_to
|
406
|
+
else
|
407
|
+
res << node
|
408
|
+
end
|
409
|
+
elsif node.is_a? N_LET or node.is_a? N_ACTION
|
410
|
+
replaced = node.dup
|
411
|
+
replaced.expr = replace_atoc(node.expr, inhs)
|
412
|
+
res << replaced
|
413
|
+
else
|
414
|
+
res << node
|
415
|
+
end
|
416
|
+
end
|
417
|
+
# warn "=====>:#{res.pretty_inspect}"
|
418
|
+
return res
|
419
|
+
end
|
420
|
+
|
421
|
+
def valid_atoc_name? atoc
|
422
|
+
return true if local_atoc?(atoc)
|
423
|
+
return true if atoc.sym_name == '$'
|
424
|
+
return grammar[atoc.rx].rhs_name_to_sym(atoc.sym_name) ? true : false
|
425
|
+
end
|
426
|
+
|
427
|
+
def valid_atoc? atoc
|
428
|
+
return true if local_atoc?(atoc)
|
429
|
+
return true if atoc.sym_name =~ /^[%#]/
|
430
|
+
rule = grammar[atoc.rx]
|
431
|
+
sym = atoc.sym_name == '$' ? rule.lhs : rule.rhs_name_to_sym(atoc.sym_name)
|
432
|
+
return true if sym and atoc.sym_name =~ /^[A-Z]/ # term(no check)
|
433
|
+
sym and @attributes[sym] and @attributes[sym].include?(atoc.attr_name)
|
434
|
+
rescue ; warn "ATOC?:#{atoc.pretty_inspect}"; false
|
435
|
+
end
|
436
|
+
|
437
|
+
def rhs_index atoc
|
438
|
+
return nil if local_atoc?(atoc)
|
439
|
+
grammar[atoc.rx].rhs_names.index(atoc.sym_name)
|
440
|
+
end
|
441
|
+
|
442
|
+
def atoc_to_sym atoc
|
443
|
+
return nil if local_atoc?(atoc)
|
444
|
+
return $1.to_i if atoc.sym_name =~ /^%(\d+)$/
|
445
|
+
return grammar[atoc.rx].lhs if atoc.sym_name == '$'
|
446
|
+
grammar[atoc.rx].rhs_name_to_sym(atoc.sym_name) rescue nil
|
447
|
+
end
|
448
|
+
|
449
|
+
def local_atoc? atoc
|
450
|
+
atoc.sym_name == nil
|
451
|
+
end
|
452
|
+
|
453
|
+
def inh_atoc? atoc
|
454
|
+
!local_atoc?(atoc) and atoc.attr_name[0] == ?_
|
455
|
+
end
|
456
|
+
|
457
|
+
def syn_atoc? atoc
|
458
|
+
!local_atoc?(atoc) and atoc.attr_name[0] != ?_
|
459
|
+
end
|
460
|
+
|
461
|
+
def pending_error *args
|
462
|
+
@pending_errors ||= []
|
463
|
+
@pending_errors << g_parser.error_message(*args)
|
464
|
+
end
|
465
|
+
|
466
|
+
def error_exit_if_error_pending
|
467
|
+
@pending_errors and (warn @pending_errors.join("\n") ; exit 1)
|
468
|
+
end
|
469
|
+
|
470
|
+
def debug_info s
|
471
|
+
Depager.debug_mode? and File.open(@debug_output_path, 'a'){|f| f.write s}
|
472
|
+
end
|
473
|
+
|
474
|
+
def generate_rie_decorator_code on_reduce, on_state, action_code
|
475
|
+
on_reduce_code = on_reduce.map{|i| " #{i||'nil'},\n"}
|
476
|
+
on_state_code = on_state.map{|i| " #{i||'nil'},\n"}
|
477
|
+
|
478
|
+
generate_decorator_code(decorator_name, "#{d_parser.parsing_method}::AdvancedParser", %{
|
479
|
+
on_reduce = [\n#{on_reduce_code.join}
|
480
|
+
]
|
481
|
+
on_state = [\n#{on_state_code.join}
|
482
|
+
]
|
483
|
+
Tables = [on_reduce, on_state]
|
484
|
+
RieATTR = Struct.new(:inh, :syn, :local)
|
485
|
+
def initialize inside
|
486
|
+
super inside
|
487
|
+
@on_reduce, @on_state = self.class::Tables
|
488
|
+
end
|
489
|
+
def before_parse
|
490
|
+
after_shift
|
491
|
+
end
|
492
|
+
def after_shift
|
493
|
+
msg = @on_state[stack.last] and send(msg)
|
494
|
+
end
|
495
|
+
def before_reduce
|
496
|
+
stack.last == 0 and after_shift
|
497
|
+
@_rie_reduce_syn = {}
|
498
|
+
mes = @on_reduce[-action_value] and send(mes)
|
499
|
+
end
|
500
|
+
require 'pp'
|
501
|
+
def after_reduce
|
502
|
+
_sstack(-1); stack[-2][decorator_index].syn = @_rie_reduce_syn
|
503
|
+
after_shift
|
504
|
+
end
|
505
|
+
def _sstack n
|
506
|
+
n = n * 2
|
507
|
+
if -n == stack.size + 1
|
508
|
+
@_attr_for_state0 ||= RieATTR[{}, {}, {}]
|
509
|
+
else
|
510
|
+
stack[n][decorator_index] ||= RieATTR[{}, stack[n][1] == :NT ? {} : stack[n][1], {}]
|
511
|
+
end
|
512
|
+
rescue
|
513
|
+
warn "N:\#{n}"
|
514
|
+
raise
|
515
|
+
end
|
516
|
+
\n#{action_code}
|
517
|
+
}) #code
|
518
|
+
end
|
519
|
+
%}
|
520
|
+
%hook post_lhs /\[/
|
521
|
+
%banner '[...]'
|
522
|
+
%inner{
|
523
|
+
def do_default
|
524
|
+
master.attributes[g_parser.lhs] = []
|
525
|
+
end
|
526
|
+
%}
|
527
|
+
%%
|
528
|
+
%LEX{
|
529
|
+
/\s+/ { }
|
530
|
+
/[a-zA-Z_]\w*/ { yield token(:ID, $&) }
|
531
|
+
']' { yield token(']'); yield token(nil) }
|
532
|
+
/./ { yield token($&) }
|
533
|
+
%}
|
534
|
+
#begin-rule
|
535
|
+
start:
|
536
|
+
'[' attr_list ']' { master.attributes[g_parser.lhs] = _attr_list }
|
537
|
+
;
|
538
|
+
attr_list:
|
539
|
+
attr { [ _attr ] }
|
540
|
+
| attr_list ',' attr
|
541
|
+
{
|
542
|
+
if _attr_list.include? _attr
|
543
|
+
warning "attribute `#{_attr}' reappeared."
|
544
|
+
_attr_list
|
545
|
+
else
|
546
|
+
_attr_list << _attr
|
547
|
+
end
|
548
|
+
}
|
549
|
+
;
|
550
|
+
attr:
|
551
|
+
ID { _ID.value }
|
552
|
+
| ID ':' ID-ec
|
553
|
+
{
|
554
|
+
unless _ID.value[0] == ?_
|
555
|
+
error_exit "EC must be inherited attribute.", _ec.lineno
|
556
|
+
else
|
557
|
+
master.ecs[[g_parser.lhs, _ID.value]] = _ec.value
|
558
|
+
end
|
559
|
+
_ID.value
|
560
|
+
}
|
561
|
+
;
|
562
|
+
#end-rule
|
563
|
+
%%
|
564
|
+
%hook post_rhs /\{/
|
565
|
+
%banner '{...}'
|
566
|
+
%inner{
|
567
|
+
attr_accessor :locals
|
568
|
+
def before_parse
|
569
|
+
@nest = 0
|
570
|
+
@locals = {}
|
571
|
+
end
|
572
|
+
def do_default
|
573
|
+
master.semantics[g_parser.rules.size-1] = []
|
574
|
+
end
|
575
|
+
def skip_space
|
576
|
+
begin
|
577
|
+
@line.match(/^[\s\n]+(#[.\n]*)?/) and @line = $'
|
578
|
+
break unless @line.empty?
|
579
|
+
end while @original_line = @line = getline
|
580
|
+
end
|
581
|
+
def getline
|
582
|
+
begin ; line = @file.gets
|
583
|
+
end while line and line =~ /^\s*(#.*)?$/
|
584
|
+
line
|
585
|
+
end
|
586
|
+
%}
|
587
|
+
%prec{
|
588
|
+
left '.'
|
589
|
+
left ID
|
590
|
+
%}
|
591
|
+
%%
|
592
|
+
%LEX{
|
593
|
+
/#.*/ { }
|
594
|
+
/[ \t]+/ { }
|
595
|
+
/\r?\n/ { yield token(';') }
|
596
|
+
/\s*\(/ { yield token('(', $&) ; skip_space }
|
597
|
+
/\s*\[/ { yield token('[', $&) ; skip_space }
|
598
|
+
/\s*\{/ { yield token('{', $&) ; skip_space ; @nest +=1 }
|
599
|
+
'}' { yield token('}'); (@nest-=1) == 0 and yield token(nil) }
|
600
|
+
'.' { yield token('.') ; @_mode = :AFTER_DOT }
|
601
|
+
',' { yield token(','); @line.match(/[\s\n]*/) and @line = $' } #'
|
602
|
+
'%transfer' { yield token(:TRANSFER) }
|
603
|
+
'%thread' { yield token(:THREAD) }
|
604
|
+
'%except' { yield token(:EXCEPT) }
|
605
|
+
'$.' { yield token(:ID, '$'); yield token('.') ; @_mode = :AFTER_DOT }
|
606
|
+
/'([^'\\]+|\\.)*'/,
|
607
|
+
/"([^"\\]+|\\.)*"/,
|
608
|
+
/\/([^\/\\]+|\\.)*\//,
|
609
|
+
/(@|$|:)[a-zA-Z_]\w*/,
|
610
|
+
/[a-zA-Z_]\w*[!?]/,
|
611
|
+
/\d+/ { yield token(:RBTOKEN, $&) }
|
612
|
+
/(<=|>=|=>|==|===|!=|and|or)/,
|
613
|
+
/([+!~*\-\/%^<>&|?:]+|\.\.\.?)/
|
614
|
+
{ yield token(:RBTOKEN, $&) ; skip_space }
|
615
|
+
'=' { yield token('=') ; skip_space }
|
616
|
+
/[a-zA-Z_]\w*/
|
617
|
+
{
|
618
|
+
if @_mode != :AFTER_DOT and @locals[$&]
|
619
|
+
yield token(:LID, $&)
|
620
|
+
else
|
621
|
+
@_mode = nil
|
622
|
+
yield token(:ID, $&)
|
623
|
+
end
|
624
|
+
}
|
625
|
+
/./ { yield token($&) }
|
626
|
+
%}
|
627
|
+
%ACTION{
|
628
|
+
include Depager::RieExtension::Nodes
|
629
|
+
%}
|
630
|
+
#begin-rule
|
631
|
+
start:
|
632
|
+
'{' stmt_list '}'
|
633
|
+
{
|
634
|
+
basis.locals.clear
|
635
|
+
master.semantics[g_parser.rules.size-1] = _stmt_list.compact
|
636
|
+
}
|
637
|
+
;
|
638
|
+
|
639
|
+
# stmt
|
640
|
+
stmt_list:
|
641
|
+
stmt
|
642
|
+
{
|
643
|
+
if _stmt.is_a? N_EXCEPT
|
644
|
+
error_exit "invalid %except.", _stmt.lineno
|
645
|
+
end
|
646
|
+
[ _stmt ]
|
647
|
+
}
|
648
|
+
| stmt_list ';' stmt
|
649
|
+
{
|
650
|
+
if _stmt.is_a? N_EXCEPT
|
651
|
+
unless [N_THREAD, N_TRANSFER].include?(_stmt_list.last.class)
|
652
|
+
error_exit "invalid %except.", _stmt.lineno
|
653
|
+
end
|
654
|
+
let_or_ids = _stmt.let_or_ids
|
655
|
+
if let_or_ids.is_a? N_LET
|
656
|
+
_stmt_list.last.excepts << let_or_ids.atoc
|
657
|
+
_stmt_list.insert(_stmt_list.size-1, let_or_ids)
|
658
|
+
else
|
659
|
+
_stmt_list.last.excepts.concat(let_or_ids)
|
660
|
+
_stmt_list
|
661
|
+
end
|
662
|
+
else
|
663
|
+
_stmt ? (_stmt_list << _stmt) : _stmt_list
|
664
|
+
end
|
665
|
+
}
|
666
|
+
;
|
667
|
+
stmt:
|
668
|
+
{ nil }
|
669
|
+
| THREAD id_list { N_THREAD[val[0].lineno, _id_list, []] }
|
670
|
+
| TRANSFER id_list { N_TRANSFER[val[0].lineno, _id_list, []] }
|
671
|
+
| EXCEPT lhs_list { N_EXCEPT[val[0].lineno, lhs_list] }
|
672
|
+
| EXCEPT lhs '=' rbexpr { N_EXCEPT[val[0].lineno, N_LET[_lhs.lineno, _lhs, _rbexpr]]}
|
673
|
+
| lhs '=' rbexpr { N_LET[_lhs.lineno, _lhs, _rbexpr] }
|
674
|
+
| LID '=' rbexpr
|
675
|
+
{
|
676
|
+
N_LET[val[0].lineno, N_ATOC[val[0].lineno, nil, _LID.value, g_parser.rules.size-1], _rbexpr]
|
677
|
+
}
|
678
|
+
| ID '=' rbexpr
|
679
|
+
{
|
680
|
+
basis.locals[_ID.value] = true
|
681
|
+
N_LET[val[0].lineno, N_ATOC[val[0].lineno, nil, _ID.value, g_parser.rules.size-1], _rbexpr]
|
682
|
+
}
|
683
|
+
| rbexpr { N_ACTION[basis.file.lineno, _rbexpr ] }
|
684
|
+
;
|
685
|
+
# rbexpr
|
686
|
+
rbexpr_list:
|
687
|
+
rbexpr { _rbexpr }
|
688
|
+
| rbexpr_list ';' { _rbexpr_list }
|
689
|
+
| rbexpr_list ';' rbexpr { (_rbexpr_list << ';').concat _rbexpr}
|
690
|
+
;
|
691
|
+
rbexpr:
|
692
|
+
rbelem { _rbelem }
|
693
|
+
| rbexpr rbelem { _rbexpr.concat _rbelem }
|
694
|
+
;
|
695
|
+
rbelem:
|
696
|
+
lhs { [_lhs] }
|
697
|
+
| ID { [_ID.value] }
|
698
|
+
| LID { [ N_ATOC[_LID.lineno, nil, _LID.value, g_parser.rules.size-1] ] }
|
699
|
+
| RBTOKEN { [_RBTOKEN.value] }
|
700
|
+
| '.' { ['.'] }
|
701
|
+
| ',' { [','] }
|
702
|
+
| '[' ']' { [ val[0].value, ']' ] }
|
703
|
+
| '[' rbexpr_list ']' { [ val[0].value ].concat(_rbexpr_list) << ']' }
|
704
|
+
| '{' '}' { [ val[0].value, '}' ]}
|
705
|
+
| '{' rbexpr_list '}' { [ val[0].value ].concat(_rbexpr_list) << '}' }
|
706
|
+
| '(' ')' { [ val[0].value, ')' ]}
|
707
|
+
| '(' rbexpr_list ')' { [ val[0].value ].concat(_rbexpr_list) << ')' }
|
708
|
+
;
|
709
|
+
|
710
|
+
# lhs
|
711
|
+
lhs_list:
|
712
|
+
lhs { [ _lhs ]}
|
713
|
+
| lhs_list ',' lhs { lhs_list << lhs }
|
714
|
+
;
|
715
|
+
lhs:
|
716
|
+
ID '.' ID-attr { N_ATOC[_ID.lineno, _ID.value, _attr.value, g_parser.rules.size-1] }
|
717
|
+
;
|
718
|
+
id_list:
|
719
|
+
ID { [ _ID.value ] }
|
720
|
+
| id_list ',' ID { _id_list << _ID.value }
|
721
|
+
;
|
722
|
+
#end-rule
|
723
|
+
%%
|