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.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/README.en +4 -19
  3. data/README.ja +42 -79
  4. data/bin/depager +42 -45
  5. data/examples/action_pl0d/pl0d.action.dr +421 -0
  6. data/examples/action_pl0d/test.pl0ds +49 -0
  7. data/examples/c89/c89.dr +493 -496
  8. data/examples/c89/test.c89 +10 -10
  9. data/examples/extension/astdf.rb +10 -0
  10. data/examples/extension/atree.dr +55 -0
  11. data/examples/{sample_calc → extension}/calc.atree.dr +42 -43
  12. data/examples/extension/calc.simple_action.dr +33 -0
  13. data/examples/extension/paction.dr +16 -15
  14. data/examples/extension/pactiontest.dr +14 -14
  15. data/examples/extension/simple_action.rb +44 -0
  16. data/examples/pl0d/pl0ds.dr +337 -334
  17. data/examples/pl0d/test.pl0ds +33 -33
  18. data/examples/rie_calc/calc.rie.dr +57 -0
  19. data/examples/rie_calc/test.calc +4 -0
  20. data/examples/rie_dcuse/dcuse.rie.dr +71 -0
  21. data/examples/rie_dcuse/test.dcuse +1 -0
  22. data/examples/rie_pl0/orig_ex/exerrdg.pl0 +44 -0
  23. data/examples/rie_pl0/orig_ex/exerrm.pl0 +19 -0
  24. data/examples/rie_pl0/orig_ex/exerrmre.pl0 +20 -0
  25. data/examples/rie_pl0/orig_ex/exerrtok.pl0 +18 -0
  26. data/examples/rie_pl0/orig_ex/exmdg.pl0 +40 -0
  27. data/examples/rie_pl0/orig_ex/exmdgwwl.pl0 +43 -0
  28. data/examples/rie_pl0/orig_ex/exmrw.pl0 +22 -0
  29. data/examples/rie_pl0/orig_ex/exmwwl.pl0 +18 -0
  30. data/examples/rie_pl0/orig_ex/exnorw.pl0 +17 -0
  31. data/examples/rie_pl0/pl0.rie.dr +450 -0
  32. data/examples/rie_pl0/test.pl0 +10 -0
  33. data/examples/sample_calc/calc.action.dr +33 -33
  34. data/examples/sample_calc/calc.ast.action.dr +65 -66
  35. data/examples/sample_calc/calc.ast.dr +55 -55
  36. data/examples/sample_calc/calc.cst.dr +45 -45
  37. data/examples/sample_calc/calc.dr +43 -43
  38. data/examples/sample_calc/calc.lex.dr +29 -29
  39. data/examples/sample_calc/{calc_prec.nvaction.dr → calc_prec.action.dr} +31 -31
  40. data/examples/slex_test/divreg.slex.dr +29 -29
  41. data/examples/slex_test/ljoin.slex.dr +36 -36
  42. data/examples/slex_test/test.divreg +1 -1
  43. data/examples/slex_test/test.ljoin +3 -3
  44. data/lib/depager.rb +582 -670
  45. data/lib/depager/grammar.rb +256 -291
  46. data/lib/depager/lr.rb +574 -579
  47. data/lib/depager/parser.rb +282 -277
  48. data/lib/depager/ruby/plugins/_rie_debug.rb +35 -0
  49. data/lib/depager/ruby/plugins/action.rb +53 -43
  50. data/lib/depager/ruby/plugins/ast.dr +364 -269
  51. data/lib/depager/ruby/plugins/ast.rb +1367 -1308
  52. data/lib/depager/ruby/plugins/cst.dr +172 -180
  53. data/lib/depager/ruby/plugins/cst.rb +587 -626
  54. data/lib/depager/ruby/plugins/lex.dr +85 -89
  55. data/lib/depager/ruby/plugins/lex.rb +310 -336
  56. data/lib/depager/ruby/plugins/rie.dr +723 -0
  57. data/lib/depager/ruby/plugins/rie.rb +1653 -0
  58. data/lib/depager/ruby/plugins/slex.dr +202 -200
  59. data/lib/depager/ruby/plugins/slex.rb +780 -817
  60. data/lib/depager/ruby/plugins/srp.rb +56 -51
  61. data/lib/depager/ruby/templates/extension_lalr_master.erb +46 -51
  62. data/lib/depager/ruby/templates/extension_lalr_slave.erb +99 -107
  63. data/lib/depager/ruby/templates/single_lalr_parser.erb +115 -117
  64. data/lib/depager/utils.rb +148 -318
  65. data/lib/depager/version.rb +4 -3
  66. metadata +52 -60
  67. data/ChangeLog +0 -16
  68. data/data/depager/pre-setup.rb +0 -3
  69. data/examples/c89/c89.tab.rb +0 -7127
  70. data/examples/pl0d/pl0ds.tab.rb +0 -2698
  71. data/examples/sample_calc/calc.action.tab.rb +0 -457
  72. data/examples/sample_calc/calc.ast.action.tab.rb +0 -749
  73. data/examples/sample_calc/calc.ast.tab.rb +0 -665
  74. data/examples/sample_calc/calc.astdf.dr +0 -54
  75. data/examples/sample_calc/calc.astdf.tab.rb +0 -672
  76. data/examples/sample_calc/calc.atree.tab.rb +0 -451
  77. data/examples/sample_calc/calc.cst.tab.rb +0 -644
  78. data/examples/sample_calc/calc.lex.tab.rb +0 -374
  79. data/examples/sample_calc/calc.nvaction.dr +0 -33
  80. data/examples/sample_calc/calc.nvaction.tab.rb +0 -465
  81. data/examples/sample_calc/calc.tab.rb +0 -365
  82. data/examples/sample_calc/calc_prec.nvaction.tab.rb +0 -431
  83. data/examples/slex_test/divreg.slex.tab.rb +0 -303
  84. data/examples/slex_test/ljoin.slex.tab.rb +0 -370
  85. data/lib/depager/ruby/plugins/_ast_tmpl.rb +0 -73
  86. data/lib/depager/ruby/plugins/astdf.rb +0 -6
  87. data/lib/depager/ruby/plugins/atree.dr +0 -55
  88. data/lib/depager/ruby/plugins/atree.rb +0 -347
  89. data/lib/depager/ruby/plugins/nvaction.rb +0 -19
  90. data/lib/depager/ruby/templates/simple.erb +0 -23
  91. 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
+ %%