depager 0.2.3 → 0.3.0.b20160729
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 +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
|
+
%%
|