depager 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +4 -0
- data/Manifest.txt +52 -0
- data/README.en +64 -0
- data/README.ja +128 -0
- data/bin/depager +47 -0
- data/data/depager/misc/depager-mode.el +209 -0
- data/data/depager/sample/extension/paction.dr +15 -0
- data/data/depager/sample/extension/pactiontest.dr +14 -0
- data/data/depager/sample/pl0d/pl0ds.dr +334 -0
- data/data/depager/sample/pl0d/pl0test.pl0 +34 -0
- data/data/depager/sample/sample_calc/calc.action.dr +33 -0
- data/data/depager/sample/sample_calc/calc.astdf.dr +54 -0
- data/data/depager/sample/sample_calc/calc.astl.action.dr +66 -0
- data/data/depager/sample/sample_calc/calc.astl.dr +55 -0
- data/data/depager/sample/sample_calc/calc.atree.dr +43 -0
- data/data/depager/sample/sample_calc/calc.cst.dr +45 -0
- data/data/depager/sample/sample_calc/calc.dr +43 -0
- data/data/depager/sample/sample_calc/calc.lex.dr +29 -0
- data/data/depager/sample/sample_calc/calc.nvaction.dr +33 -0
- data/data/depager/sample/sample_calc/calc_prec.nvaction.dr +31 -0
- data/data/depager/sample/slex_test/slextest1.dr +37 -0
- data/data/depager/sample/slex_test/slextest2.dr +33 -0
- data/lib/depager.rb +608 -0
- data/lib/depager/Rakefile +30 -0
- data/lib/depager/action.rb +47 -0
- data/lib/depager/ast_base.dr +232 -0
- data/lib/depager/ast_base.rb +1249 -0
- data/lib/depager/astdf.rb +10 -0
- data/lib/depager/astl.rb +14 -0
- data/lib/depager/atree.dr +55 -0
- data/lib/depager/atree.rb +336 -0
- data/lib/depager/cst.dr +182 -0
- data/lib/depager/cst.rb +625 -0
- data/lib/depager/lex.dr +76 -0
- data/lib/depager/lex.rb +306 -0
- data/lib/depager/lr.rb +604 -0
- data/lib/depager/nvaction.rb +21 -0
- data/lib/depager/parse_action.rb +24 -0
- data/lib/depager/parser.rb +248 -0
- data/lib/depager/psrtmpl.rb +33 -0
- data/lib/depager/slex.dr +161 -0
- data/lib/depager/slex.rb +646 -0
- data/lib/depager/srp.rb +50 -0
- data/lib/depager/template/astdf.erbs +57 -0
- data/lib/depager/template/astl.erbs +57 -0
- data/lib/depager/template/extension_lalr_master.erb +51 -0
- data/lib/depager/template/extension_lalr_slave.erb +107 -0
- data/lib/depager/template/simple.erb +21 -0
- data/lib/depager/template/single_lalr_parser.erb +97 -0
- data/lib/depager/utils.rb +355 -0
- data/lib/depager/version.rb +9 -0
- data/setup.rb +1585 -0
- metadata +103 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'depager/action.rb'
|
2
|
+
require 'depager/parser.rb'
|
3
|
+
require 'depager/parse_action.rb'
|
4
|
+
|
5
|
+
class NVActionExtension < ActionExtension #:nodoc:all
|
6
|
+
def modify_action_code code
|
7
|
+
let_code = ""
|
8
|
+
if @g_parser.rhsni.size > 0
|
9
|
+
rhs = @g_parser.rhsni.sort_by{|k,v| v}
|
10
|
+
let_code = rhs.map do |name, _|
|
11
|
+
if name =~ /[a-zA-Z][a-zA-Z0-9_]*/
|
12
|
+
"_#{name}"
|
13
|
+
else
|
14
|
+
'_'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
let_code = " #{let_code.join(', ')} = *val \n"
|
18
|
+
end
|
19
|
+
return let_code << code, 1
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Depager::ActionParser
|
2
|
+
require 'pp'
|
3
|
+
def parse_action
|
4
|
+
val = ''
|
5
|
+
start_lineno = lineno
|
6
|
+
if @line =~ /\A\{(.*)\}\s*(#.*)?\Z/
|
7
|
+
val = " #{$1}\n"
|
8
|
+
else
|
9
|
+
val.concat @line.sub(/\A\s*\{/, '')
|
10
|
+
ind = @line0.match(/\A([ \t]*)/)[1]
|
11
|
+
until file.eof?
|
12
|
+
getline
|
13
|
+
break if line =~ /\A#{ind}\}\s*(#.*)?\Z/
|
14
|
+
val.concat line
|
15
|
+
end
|
16
|
+
if file.eof?
|
17
|
+
error_exit 'syntax error(parse_action).', start_lineno
|
18
|
+
end
|
19
|
+
end
|
20
|
+
@line = $'
|
21
|
+
#warn val
|
22
|
+
return val
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
require "depager/utils.rb"
|
2
|
+
module Depager
|
3
|
+
#
|
4
|
+
# Token
|
5
|
+
#
|
6
|
+
Token = Struct.new(:value, :lineno, :filename)
|
7
|
+
|
8
|
+
# = Parser Runtime
|
9
|
+
# == Stack
|
10
|
+
# s:: state
|
11
|
+
# la:: look ahead
|
12
|
+
# v:: value
|
13
|
+
# stack top->
|
14
|
+
# [0, [la0, v0], s0, [la1, v1], s1, .....]
|
15
|
+
#
|
16
|
+
class Parser
|
17
|
+
def initialize
|
18
|
+
end
|
19
|
+
|
20
|
+
ACC = 0x03ffffff
|
21
|
+
|
22
|
+
#
|
23
|
+
# lexer
|
24
|
+
#
|
25
|
+
def lex
|
26
|
+
end
|
27
|
+
|
28
|
+
# parse method
|
29
|
+
def yyparse f
|
30
|
+
@basis.file = f
|
31
|
+
@basis.la = [0, nil]
|
32
|
+
@basis.lex do |sym, val|
|
33
|
+
@basis.la = [@basis.t2i[sym] || @basis.t2i[false], val]
|
34
|
+
break if driver
|
35
|
+
end
|
36
|
+
@basis.stack[1][2..(@basis.params.size+1)]
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
def init_parser
|
41
|
+
end
|
42
|
+
|
43
|
+
# driver method
|
44
|
+
def driver
|
45
|
+
while true
|
46
|
+
@basis.val = @basis.action_table[@basis.stack.last][@basis.la[0]]
|
47
|
+
@basis.val ||= @basis.defred_table[@basis.stack.last]
|
48
|
+
|
49
|
+
if @basis.val == nil
|
50
|
+
#warn "#{@basis.stack}#{@basis.la[0]}"
|
51
|
+
error
|
52
|
+
exit 1
|
53
|
+
elsif @basis.val == ACC
|
54
|
+
if @i2t[@basis.la[0]] == nil
|
55
|
+
accept
|
56
|
+
else
|
57
|
+
error
|
58
|
+
end
|
59
|
+
return true
|
60
|
+
elsif @basis.val > 0
|
61
|
+
shift
|
62
|
+
while val = @basis.defred_after_shift_table[@basis.stack.last]
|
63
|
+
@basis.val = val
|
64
|
+
reduce
|
65
|
+
end
|
66
|
+
return false
|
67
|
+
else
|
68
|
+
reduce
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
def accept
|
73
|
+
end
|
74
|
+
def error
|
75
|
+
end
|
76
|
+
def shift
|
77
|
+
end
|
78
|
+
def reduce
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class Basis < Parser
|
83
|
+
attr_accessor :state, :stack, :laq, :la, :val, :basis, :params
|
84
|
+
attr_accessor :file, :oldline, :lineno, :line, :line0
|
85
|
+
attr_reader :action_table, :defred_table, :defred_after_shift_table
|
86
|
+
attr_reader :goto_table, :reduce_table
|
87
|
+
attr_reader :i2t, :t2i, :nt2i, :i2nt
|
88
|
+
|
89
|
+
private
|
90
|
+
def __init_parser__
|
91
|
+
@state = 0
|
92
|
+
@stack = [@state]
|
93
|
+
@laq = []
|
94
|
+
@la = nil
|
95
|
+
@val = nil
|
96
|
+
@line0 = @line = ''
|
97
|
+
end
|
98
|
+
|
99
|
+
def initialize
|
100
|
+
__init_parser__
|
101
|
+
@file = nil
|
102
|
+
@basis = self
|
103
|
+
@reduce_table, @params, @action_table,
|
104
|
+
@defred_table, @defred_after_shift_table, @goto_table,
|
105
|
+
@t2i, @i2t, @nt2i, @i2nt = self.class::Tables
|
106
|
+
end
|
107
|
+
|
108
|
+
def _Token sym, val=nil, lineno=nil
|
109
|
+
lineno ||= file.lineno
|
110
|
+
return sym, Token[val, lineno, file.path]
|
111
|
+
end
|
112
|
+
|
113
|
+
public
|
114
|
+
def banner
|
115
|
+
self.class.name
|
116
|
+
end
|
117
|
+
|
118
|
+
def getline
|
119
|
+
@file.gets unless @file.eof?
|
120
|
+
end
|
121
|
+
|
122
|
+
def accept
|
123
|
+
#warn "acc."
|
124
|
+
end
|
125
|
+
def error
|
126
|
+
fname = @file.respond_to?(:path) ? @file.path : '-'
|
127
|
+
exp = []
|
128
|
+
@action_table[@stack.last].each_with_index do |i, x|
|
129
|
+
exp << @i2t[x] if i
|
130
|
+
end
|
131
|
+
la = @la[1].value rescue @la[1]
|
132
|
+
la = (@i2t[@la[0]] || la).inspect
|
133
|
+
exp = exp.map{|i| i ? i.inspect : '$' }.join(', ')
|
134
|
+
warn "#{fname}:#{@file.lineno}: syntax error(#{self.banner}), " <<
|
135
|
+
"unexpected #{la}, expecting #{exp}."
|
136
|
+
warn @stack.pretty_inspect if $MP_DEBUG
|
137
|
+
end
|
138
|
+
def shift
|
139
|
+
@stack.push(@la).push(@val)
|
140
|
+
end
|
141
|
+
def reduce
|
142
|
+
(@reduce_table[-@val][1] * 2).times{@stack.pop}
|
143
|
+
r = @reduce_table[-@val][0]
|
144
|
+
cs = @goto_table[@stack.last][r]
|
145
|
+
@stack.push([r, :NT]).push(cs)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
#
|
150
|
+
# Decorator Base class
|
151
|
+
#
|
152
|
+
class AdvancedParser < Parser
|
153
|
+
attr_reader :basis
|
154
|
+
attr_reader :action_table, :goto_table, :reduce_table
|
155
|
+
attr_reader :i2t, :t2i, :nt2i, :i2nt
|
156
|
+
def initialize inside, paramkey = nil
|
157
|
+
@inside = inside
|
158
|
+
@basis = @inside.basis
|
159
|
+
@reduce_table, @params, @action_table, @defred_table, @goto_table,
|
160
|
+
@t2i, @i2t, @nt2i, @i2nt = @basis.class::Tables
|
161
|
+
@nparam = @params[paramkey]
|
162
|
+
end
|
163
|
+
|
164
|
+
protected
|
165
|
+
def _state
|
166
|
+
@basis.state
|
167
|
+
end
|
168
|
+
def _stack
|
169
|
+
@basis.stack
|
170
|
+
end
|
171
|
+
def _lookaheadque
|
172
|
+
@basis.laq
|
173
|
+
end
|
174
|
+
def _lookahead
|
175
|
+
@basis.la
|
176
|
+
end
|
177
|
+
def _actvalue
|
178
|
+
@basis.val
|
179
|
+
end
|
180
|
+
|
181
|
+
def accept
|
182
|
+
beforeAccept
|
183
|
+
@inside.accept
|
184
|
+
afterAccept
|
185
|
+
end
|
186
|
+
def error
|
187
|
+
beforeError
|
188
|
+
@inside.error
|
189
|
+
afterError
|
190
|
+
end
|
191
|
+
def shift
|
192
|
+
beforeShift
|
193
|
+
@inside.shift
|
194
|
+
afterShift
|
195
|
+
end
|
196
|
+
def reduce
|
197
|
+
beforeReduce
|
198
|
+
@inside.reduce
|
199
|
+
afterReduce
|
200
|
+
end
|
201
|
+
|
202
|
+
def beforeAccept
|
203
|
+
end
|
204
|
+
def afterAccept
|
205
|
+
end
|
206
|
+
def beforeError
|
207
|
+
end
|
208
|
+
def afterError
|
209
|
+
end
|
210
|
+
def beforeShift
|
211
|
+
end
|
212
|
+
def afterShift
|
213
|
+
end
|
214
|
+
def beforeReduce
|
215
|
+
end
|
216
|
+
def afterReduce
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
#
|
221
|
+
# Action Decorator Base class
|
222
|
+
#
|
223
|
+
class Action < AdvancedParser
|
224
|
+
def initialize inside, nparamkey=nil
|
225
|
+
super inside, nparamkey
|
226
|
+
@_yy_val_ = []
|
227
|
+
end
|
228
|
+
def beforeReduce
|
229
|
+
@_yy_val_ = []
|
230
|
+
n = @reduce_table[-_actvalue][1]
|
231
|
+
n.times do |i|
|
232
|
+
x = _stack[_stack.size-2*(i+1)]
|
233
|
+
@_yy_val_[n-i-1] = x[1] == :NT ? x[@nparam] : x[1]
|
234
|
+
end
|
235
|
+
end
|
236
|
+
def afterReduce
|
237
|
+
mes = @on_reduce[-_actvalue]
|
238
|
+
r = mes ? self.send(mes, @_yy_val_) : nil
|
239
|
+
_stack[_stack.size-2][@nparam] = r
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
class IO
|
245
|
+
def path
|
246
|
+
self.to_s
|
247
|
+
end
|
248
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class ShiftReducePrinter < AdvancedParser
|
2
|
+
def initialize inside
|
3
|
+
super
|
4
|
+
end
|
5
|
+
def beforeAccept
|
6
|
+
end
|
7
|
+
def afterAccept
|
8
|
+
end
|
9
|
+
def beforeError
|
10
|
+
end
|
11
|
+
def afterError
|
12
|
+
end
|
13
|
+
def beforeShift
|
14
|
+
end
|
15
|
+
def afterShift
|
16
|
+
super
|
17
|
+
st = _stack.last
|
18
|
+
sh = @i2t[_stack[_stack.size-2]]
|
19
|
+
la = @i2t[_lookahead]
|
20
|
+
warn "shift:<#{sh}> #{st} lookahead:<#{la}>"
|
21
|
+
warn _stack
|
22
|
+
end
|
23
|
+
def beforeReduce
|
24
|
+
end
|
25
|
+
def afterReduce
|
26
|
+
super
|
27
|
+
st = _stack.last
|
28
|
+
re = @i2nt[_stack[_stack.size-2]]
|
29
|
+
la = @i2t[_lookahead]
|
30
|
+
warn "reduse:<#{re}> #{st} lookahead:<#{la}>"
|
31
|
+
warn _stack
|
32
|
+
end
|
33
|
+
end
|
data/lib/depager/slex.dr
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
%defext StatefulLexerExtension
|
2
|
+
%extend Lexer ('depager/lex.rb')
|
3
|
+
%extend NVAction ('depager/nvaction.rb')
|
4
|
+
%decorate @NVAction
|
5
|
+
#%decorate ShiftReducePrinter ('depager/srp.rb')
|
6
|
+
%inner{
|
7
|
+
attr_accessor :ins, :code, :optval
|
8
|
+
def init_parser
|
9
|
+
super
|
10
|
+
@ins = []
|
11
|
+
@optouter = []
|
12
|
+
@on_reduce = []
|
13
|
+
@addition = []
|
14
|
+
end
|
15
|
+
def postRuleList
|
16
|
+
@optouter << %{
|
17
|
+
def afterError
|
18
|
+
warn "StatefulLex: lex_state==\#{@basis.lex_state}" if $MP_DEBUG
|
19
|
+
end
|
20
|
+
}
|
21
|
+
g_parser.optouter <<
|
22
|
+
gen_action_decorator_code(target_name, paramkey,
|
23
|
+
@on_reduce, @optouter)
|
24
|
+
end
|
25
|
+
def postRhs
|
26
|
+
j = 0
|
27
|
+
rhs = g_parser.rhs
|
28
|
+
@ins.each do |i, m|
|
29
|
+
state_name = "#{lhs_name}_#{nrhs}_#{i}"
|
30
|
+
if i != rhs.size
|
31
|
+
isym = g_parser.add_nonterm("__#{state_name}__".intern)
|
32
|
+
new_rule = Rule[isym, []]
|
33
|
+
val = ( ":_lex_#{state_name}" )
|
34
|
+
@addition << [ new_rule, rhs, val, i+j, isym ]
|
35
|
+
j += 1
|
36
|
+
else
|
37
|
+
@on_reduce[nrules] = ( ":_lex_#{state_name}" )
|
38
|
+
end
|
39
|
+
@optouter.push << %{
|
40
|
+
def _lex_#{lhs_name}_#{nrhs}_#{i} val
|
41
|
+
@basis.lex_state = #{m}
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
@ins.clear
|
46
|
+
end
|
47
|
+
def postRhsList
|
48
|
+
@addition.each do |new_rule, rhs, val, pos, isym|
|
49
|
+
g_parser.g << new_rule
|
50
|
+
rhs.insert(pos, isym)
|
51
|
+
@on_reduce[nrules] = val
|
52
|
+
end
|
53
|
+
@addition.clear
|
54
|
+
end
|
55
|
+
%}
|
56
|
+
######################################################################
|
57
|
+
# Define Tokens
|
58
|
+
######################################################################
|
59
|
+
%hook prerulelist /%LEX\{\s*\Z/ skip
|
60
|
+
%mixin ActionParser ('depager/parse_action')
|
61
|
+
%banner '%LEX{ ... }'
|
62
|
+
%%
|
63
|
+
%LEX{
|
64
|
+
/\s+/, /#.*\Z/ { }
|
65
|
+
/[A-Z]+/ { yield _Token(:ID, $&) }
|
66
|
+
/\%\}\s*\Z/ { @line = $'; yield nil,nil }
|
67
|
+
/\/(([^\/\\]+|\\.)*)\//,
|
68
|
+
/'([^'\\]+|\\.)*\'/ { yield _Token(:LEX, "/\\A#{$1}/") }
|
69
|
+
/\{/ { ln = lineno; yield :ACTION, Token[parse_action, ln]; //=~'' }
|
70
|
+
/./ { yield _Token($&, $&) }
|
71
|
+
%}
|
72
|
+
#begin-rule
|
73
|
+
start:
|
74
|
+
mode_list
|
75
|
+
{
|
76
|
+
ll = ''
|
77
|
+
_mode_list.each do |m, s, l|
|
78
|
+
elsec = if s
|
79
|
+
"_rest = lex_#{s}(&block)"
|
80
|
+
else
|
81
|
+
%!raise RuntimeError, "must not happen \#{@line}"!
|
82
|
+
end
|
83
|
+
ll << %{
|
84
|
+
def lex_#{m}(&block)
|
85
|
+
_rest = ''
|
86
|
+
case @line
|
87
|
+
#{l.map{|i| ' '*4+i}}
|
88
|
+
else
|
89
|
+
#{elsec}
|
90
|
+
end
|
91
|
+
return _rest
|
92
|
+
end
|
93
|
+
}; #code
|
94
|
+
end
|
95
|
+
g_parser.optinner << ll << %{
|
96
|
+
attr_accessor :lex_state
|
97
|
+
def lex(&block)
|
98
|
+
@lex_state ||= :START
|
99
|
+
begin
|
100
|
+
until @line.empty?
|
101
|
+
@line = self.send "lex_\#{@lex_state}", &block
|
102
|
+
end
|
103
|
+
end while @line = getline
|
104
|
+
yield nil, nil
|
105
|
+
end
|
106
|
+
}; #code
|
107
|
+
}
|
108
|
+
;
|
109
|
+
mode_list:
|
110
|
+
{ [ ] }
|
111
|
+
| mode_list mode lexactlist { _mode_list << [_mode[0], _mode[1], _lexactlist] }
|
112
|
+
;
|
113
|
+
mode:
|
114
|
+
'<' ID opt_super '>' { [ _ID.value, _opt_super ] }
|
115
|
+
;
|
116
|
+
opt_super:
|
117
|
+
{ nil }
|
118
|
+
| ':' ID { _ID.value }
|
119
|
+
;
|
120
|
+
lexactlist:
|
121
|
+
lexact { [ _lexact ] }
|
122
|
+
| lexactlist lexact { _lexactlist << _lexact }
|
123
|
+
;
|
124
|
+
lexact:
|
125
|
+
lexlist ACTION
|
126
|
+
{
|
127
|
+
%{
|
128
|
+
when #{_lexlist.join(', ')}
|
129
|
+
_rest = $'
|
130
|
+
#{ _ACTION.value }
|
131
|
+
}; #code
|
132
|
+
}
|
133
|
+
;
|
134
|
+
lexlist:
|
135
|
+
LEX { [ _LEX.value ] }
|
136
|
+
| lexlist ',' LEX { _lexlist.push _LEX }
|
137
|
+
;
|
138
|
+
#end-rule
|
139
|
+
%%
|
140
|
+
######################################################################
|
141
|
+
# Change State
|
142
|
+
######################################################################
|
143
|
+
%hook prerhs postsymbol /\[/
|
144
|
+
%banner '[> ...]'
|
145
|
+
%%
|
146
|
+
%LEX{
|
147
|
+
/\s+/ { }
|
148
|
+
/:[a-zA-Z_]+/ { yield _Token(:SYMBOL, $&) }
|
149
|
+
/\]/ { yield _Token($&, $&); @line = $'; yield nil, nil }
|
150
|
+
/./ { yield _Token($&, $&) }
|
151
|
+
%}
|
152
|
+
|
153
|
+
#begin-rule
|
154
|
+
start:
|
155
|
+
'[' '>' SYMBOL ']'
|
156
|
+
{
|
157
|
+
master.ins.push [g_parser.rhs.size, _SYMBOL.value]
|
158
|
+
}
|
159
|
+
;
|
160
|
+
#end-rule
|
161
|
+
%%
|