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,15 @@
|
|
1
|
+
%defext PseudoActionExtension
|
2
|
+
%extend Lexer ('depager/lex.rb')
|
3
|
+
%extend Action ('depager/action.rb')
|
4
|
+
%decorate @Action ('depager/action.rb')
|
5
|
+
#%decorate ShiftReducePrinter ('depager/srp.rb')
|
6
|
+
%hook postrhs
|
7
|
+
%%
|
8
|
+
%LEX{
|
9
|
+
/\s/ { }
|
10
|
+
/./ { yield $&, $&, @lineno }
|
11
|
+
%}
|
12
|
+
start:
|
13
|
+
'{' '}' { warn 'HIT' }
|
14
|
+
;
|
15
|
+
%%
|
@@ -0,0 +1,334 @@
|
|
1
|
+
%class PL0d
|
2
|
+
%extend Lexer ('depager/lex.rb')
|
3
|
+
%extend ASTBuilderLazy ('depager/astl.rb')
|
4
|
+
%decorate @ASTBuilderLazy
|
5
|
+
#%decorate ShiftReducePrinter ('depager/srp.rb')
|
6
|
+
%%
|
7
|
+
%LEX{
|
8
|
+
/\s+/ { }
|
9
|
+
':=' { yield _Token(:COLOEQ, $&) }
|
10
|
+
'<>' { yield _Token(:NOTEQ, $&) }
|
11
|
+
'<=' { yield _Token(:LE, $&) }
|
12
|
+
'>=' { yield _Token(:GE, $&) }
|
13
|
+
'=' { yield _Token(:EQ, $&) }
|
14
|
+
'<' { yield _Token(:LT, $&) }
|
15
|
+
'>' { yield _Token(:GT, $&) }
|
16
|
+
'const' { yield _Token(:CONST, $&) }
|
17
|
+
'var' { yield _Token(:VAR, $&) }
|
18
|
+
'function'{ yield _Token(:FUNCTION, $&) }
|
19
|
+
'begin' { yield _Token(:BEGINN, $&) }
|
20
|
+
'end' { yield _Token(:END, $&) }
|
21
|
+
'if' { yield _Token(:IF, $&) }
|
22
|
+
'then' { yield _Token(:THEN, $&) }
|
23
|
+
'while' { yield _Token(:WHILE, $&) }
|
24
|
+
'do' { yield _Token(:DO, $&) }
|
25
|
+
'return' { yield _Token(:RETURN, $&) }
|
26
|
+
'writeln' { yield _Token(:WRITELN, $&) }
|
27
|
+
'write' { yield _Token(:WRITE, $&) }
|
28
|
+
'odd' { yield _Token(:ODD, $&) }
|
29
|
+
/[a-zA-Z][a-zA-Z0-9_]*/
|
30
|
+
{ yield _Token(:IDENT, $&) }
|
31
|
+
/[0-9]+/ { yield _Token(:NUMBER, $&.to_i) }
|
32
|
+
/./ { yield _Token($&, $&) }
|
33
|
+
%}
|
34
|
+
|
35
|
+
%AST{
|
36
|
+
Node [value] { @value = nil }
|
37
|
+
Visitor
|
38
|
+
{
|
39
|
+
STEntry = Struct.new(:kind, :narg, :value)
|
40
|
+
def initialize
|
41
|
+
@global = {
|
42
|
+
'+' => STEntry.new(:FUNC, 2, proc{|a| a[0] + a[1] }),
|
43
|
+
'-' => STEntry.new(:FUNC, 2, proc{|a| a[0] - a[1] }),
|
44
|
+
'*' => STEntry.new(:FUNC, 2, proc{|a| a[0] * a[1] }),
|
45
|
+
'/' => STEntry.new(:FUNC, 2, proc{|a| a[0] / a[1] }),
|
46
|
+
'=' => STEntry.new(:FUNC, 2, proc{|a| a[0] == a[1] ? 1 : 0}),
|
47
|
+
'<>' => STEntry.new(:FUNC, 2, proc{|a| a[0] != a[1] ? 1 : 0}),
|
48
|
+
'<' => STEntry.new(:FUNC, 2, proc{|a| a[0] < a[1] ? 1 : 0}),
|
49
|
+
'>' => STEntry.new(:FUNC, 2, proc{|a| a[0] > a[1] ? 1 : 0}),
|
50
|
+
'<=' => STEntry.new(:FUNC, 2, proc{|a| a[0] <= a[1] ? 1 : 0}),
|
51
|
+
'>=' => STEntry.new(:FUNC, 2, proc{|a| a[0] >= a[1] ? 1 : 0}),
|
52
|
+
'odd'=> STEntry.new(:FUNC, 1, proc{|a| a[0] & 1 }),
|
53
|
+
|
54
|
+
'write' => STEntry.new(:FUNC, 1, proc{|a| print "#{a[0]} "; 1}),
|
55
|
+
'writeln' => STEntry.new(:FUNC, 0, proc{|a| puts ''; 1}),
|
56
|
+
}
|
57
|
+
@env = [@global]
|
58
|
+
end
|
59
|
+
def lookup name
|
60
|
+
@env.reverse_each{|s| return s[name] if s[name]}
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
def dump_env n = 2
|
64
|
+
n = @env.size if n > @env.size
|
65
|
+
e = @env[n..-1].map{|i| Hash[* i.map{|k, v| [k, v.value]}.flatten ] }
|
66
|
+
warn e.pretty_inspect
|
67
|
+
end
|
68
|
+
}
|
69
|
+
program(block)
|
70
|
+
{
|
71
|
+
visit(~block)
|
72
|
+
}
|
73
|
+
block(decls, stmt)
|
74
|
+
{
|
75
|
+
@env.push({})
|
76
|
+
visit(~decls)
|
77
|
+
visit(~stmt)
|
78
|
+
@env.pop
|
79
|
+
}
|
80
|
+
var_decl(-idents)
|
81
|
+
{
|
82
|
+
~idents.each do |ident|
|
83
|
+
if @env.last[ident.value]
|
84
|
+
warn "'#{ident.value}' already exist."; exit
|
85
|
+
else
|
86
|
+
@env.last[ident.value] = STEntry.new(:VAR, 0, 0)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
}
|
90
|
+
const_decl(const_inits)
|
91
|
+
{
|
92
|
+
visit(~const_inits)
|
93
|
+
}
|
94
|
+
const_init(-ident, -number)
|
95
|
+
{
|
96
|
+
if @env.last[~ident.value]
|
97
|
+
warn "'#{~ident.value}' already exist."; exit
|
98
|
+
else
|
99
|
+
@env.last[~ident.value] = STEntry.new(:CONST, 0, ~number.value)
|
100
|
+
end
|
101
|
+
}
|
102
|
+
func_decl(-ident, -params, -block)
|
103
|
+
{
|
104
|
+
if @env[0][~ident.value]
|
105
|
+
warn "'#{~ident.value}' already exist."; exit
|
106
|
+
end
|
107
|
+
body = proc do |args|
|
108
|
+
value = 0
|
109
|
+
n = @env.size
|
110
|
+
@env.push({})
|
111
|
+
value = callcc do |c|
|
112
|
+
@env.last['return'] = STEntry.new(:VAR, 0, c)
|
113
|
+
~params.each_with_index do |a, x|
|
114
|
+
@env.last[a.value] = STEntry.new(:VAR, 0, args[x])
|
115
|
+
end
|
116
|
+
visit(~block)
|
117
|
+
end
|
118
|
+
@env = @env[0, n]
|
119
|
+
value
|
120
|
+
end
|
121
|
+
@env.last[~ident.value] = STEntry.new(:FUNC, ~params.size, body)
|
122
|
+
}
|
123
|
+
nop_stmt(-nop)
|
124
|
+
{
|
125
|
+
}
|
126
|
+
assign_stmt(-ident, expr)
|
127
|
+
{
|
128
|
+
if ent = lookup(~ident.value)
|
129
|
+
unless ent.kind == :VAR
|
130
|
+
warn "'#{~ident.value}' not var."; exit
|
131
|
+
end
|
132
|
+
ent.value = visit(~expr).value
|
133
|
+
else
|
134
|
+
warn @env.pretty_inspect
|
135
|
+
warn "'#{~ident.value}' not found."; exit
|
136
|
+
end
|
137
|
+
}
|
138
|
+
begin_stmt(stmt, stmts)
|
139
|
+
{
|
140
|
+
visit(~stmt)
|
141
|
+
visit(~stmts)
|
142
|
+
}
|
143
|
+
if_stmt(cond, stmt)
|
144
|
+
{
|
145
|
+
if visit(~cond).value != 0
|
146
|
+
visit(~stmt)
|
147
|
+
end
|
148
|
+
}
|
149
|
+
while_stmt(cond, stmt)
|
150
|
+
{
|
151
|
+
while visit(~cond).value != 0
|
152
|
+
visit(~stmt)
|
153
|
+
end
|
154
|
+
}
|
155
|
+
return_stmt(expr)
|
156
|
+
{
|
157
|
+
ent = nil
|
158
|
+
@env.reverse_each{|s| break if ent = s['return'] }
|
159
|
+
unless ent
|
160
|
+
warn "'return' not in func."; exit
|
161
|
+
end
|
162
|
+
ent.value.call(visit(~expr).value)
|
163
|
+
}
|
164
|
+
apply(-ident, -args)
|
165
|
+
{
|
166
|
+
ent = nil
|
167
|
+
@env.reverse_each{|s| break if ent = s[~ident.value] }
|
168
|
+
unless ent
|
169
|
+
warn "'#{~ident.value}' not found."; exit
|
170
|
+
end
|
171
|
+
unless ent.kind == :FUNC
|
172
|
+
warn "'#{~ident.value}' not func."; exit
|
173
|
+
end
|
174
|
+
|
175
|
+
args = ~args.map{|a| visit(a).value }
|
176
|
+
# warn "#{' '*(@env.size-2)}|#{~ident.value} : #{args.inspect}"
|
177
|
+
unless ent.narg == args.size
|
178
|
+
warn "#{ent.narg} #{args.size} #{args.inspect}"
|
179
|
+
warn "'#{~ident.value}' unmatch args."; exit
|
180
|
+
end
|
181
|
+
~value = ent.value.call(args)
|
182
|
+
# warn "#{' '*(@env.size-2)}|-> #{~value} @ #{~ident.value}"
|
183
|
+
}
|
184
|
+
refv(-ident)
|
185
|
+
{
|
186
|
+
unless ent = lookup(~ident.value)
|
187
|
+
warn "'#{~ident.value}' not found."; exit
|
188
|
+
end
|
189
|
+
if ent.kind == :VAR || ent.kind == :CONST
|
190
|
+
~value = ent.value
|
191
|
+
else
|
192
|
+
warn "'#{~ident.value}' not var."; exit
|
193
|
+
end
|
194
|
+
}
|
195
|
+
number(-n)
|
196
|
+
{
|
197
|
+
~value = ~n.value
|
198
|
+
}
|
199
|
+
%}
|
200
|
+
#begin-rule
|
201
|
+
program:
|
202
|
+
block '.'
|
203
|
+
=> program(block)
|
204
|
+
;
|
205
|
+
|
206
|
+
block:
|
207
|
+
opt_decl_list statement
|
208
|
+
=> block(opt_decl_list, statement)
|
209
|
+
;
|
210
|
+
|
211
|
+
opt_decl_list:
|
212
|
+
=> []
|
213
|
+
| opt_decl_list decl
|
214
|
+
=> opt_decl_list << decl
|
215
|
+
;
|
216
|
+
|
217
|
+
decl:
|
218
|
+
CONST const_init_list ';'
|
219
|
+
=> const_decl(const_init_list)
|
220
|
+
| VAR ident_list ';'
|
221
|
+
=> var_decl(ident_list)
|
222
|
+
| FUNCTION IDENT '(' ')' block ';'
|
223
|
+
=> func_decl(IDENT, [], block)
|
224
|
+
| FUNCTION IDENT '(' ident_list ')' block ';'
|
225
|
+
=> func_decl(IDENT, ident_list, block)
|
226
|
+
;
|
227
|
+
|
228
|
+
const_init_list:
|
229
|
+
const_init
|
230
|
+
=> [ const_init ]
|
231
|
+
| const_init_list ',' const_init
|
232
|
+
=> const_init_list << const_init
|
233
|
+
;
|
234
|
+
|
235
|
+
const_init:
|
236
|
+
IDENT EQ NUMBER
|
237
|
+
=> const_init(IDENT, NUMBER)
|
238
|
+
;
|
239
|
+
|
240
|
+
ident_list:
|
241
|
+
IDENT
|
242
|
+
=> [ IDENT ]
|
243
|
+
| ident_list ',' IDENT
|
244
|
+
=> ident_list << IDENT
|
245
|
+
;
|
246
|
+
|
247
|
+
statement:
|
248
|
+
=> nop_stmt([])
|
249
|
+
| IDENT COLOEQ expression
|
250
|
+
=> assign_stmt(IDENT, expression)
|
251
|
+
| BEGINN statement opt_state_list END
|
252
|
+
=> begin_stmt(statement, opt_state_list)
|
253
|
+
| IF condition THEN statement
|
254
|
+
=> if_stmt(condition, statement)
|
255
|
+
| WHILE condition DO statement
|
256
|
+
=> while_stmt(condition, statement)
|
257
|
+
| RETURN expression
|
258
|
+
=> return_stmt(expression)
|
259
|
+
| WRITE expression
|
260
|
+
=> apply('write', [expression])
|
261
|
+
| WRITELN
|
262
|
+
=> apply('writeln', [])
|
263
|
+
;
|
264
|
+
|
265
|
+
opt_state_list:
|
266
|
+
=> []
|
267
|
+
| opt_state_list ';' statement
|
268
|
+
=> opt_state_list << statement
|
269
|
+
;
|
270
|
+
|
271
|
+
condition:
|
272
|
+
ODD expression
|
273
|
+
=> apply('odd', [expression])
|
274
|
+
| expression-e0 EQ expression-e1
|
275
|
+
=> apply('=', [e0, e1])
|
276
|
+
| expression-e0 NOTEQ expression-e1
|
277
|
+
=> apply('<>', [e0, e1])
|
278
|
+
| expression-e0 LT expression-e1
|
279
|
+
=> apply('<', [e0, e1])
|
280
|
+
| expression-e0 GT expression-e1
|
281
|
+
=> apply('>', [e0, e1])
|
282
|
+
| expression-e0 LE expression-e1
|
283
|
+
=> apply('<=', [e0, e1])
|
284
|
+
| expression-e0 GE expression-e1
|
285
|
+
=> apply('>=', [e0, e1])
|
286
|
+
;
|
287
|
+
|
288
|
+
expression:
|
289
|
+
expression '+' term
|
290
|
+
=> apply('+', [expression, term])
|
291
|
+
| expression '-' term
|
292
|
+
=> apply('-', [expression, term])
|
293
|
+
| term
|
294
|
+
=> term
|
295
|
+
| '-' term
|
296
|
+
=> apply('UMINUS', [term])
|
297
|
+
;
|
298
|
+
|
299
|
+
term:
|
300
|
+
term '*' factor
|
301
|
+
=> apply('*', [term, factor])
|
302
|
+
| term '/' factor
|
303
|
+
=> apply('/', [term, factor])
|
304
|
+
| factor
|
305
|
+
=> factor
|
306
|
+
;
|
307
|
+
|
308
|
+
factor:
|
309
|
+
IDENT
|
310
|
+
=> refv(IDENT)
|
311
|
+
| NUMBER
|
312
|
+
=> number(NUMBER)
|
313
|
+
| IDENT '(' ')'
|
314
|
+
=> apply(IDENT, [])
|
315
|
+
| IDENT '(' exp_list ')'
|
316
|
+
=> apply(IDENT, exp_list)
|
317
|
+
| '(' expression ')'
|
318
|
+
=> expression
|
319
|
+
;
|
320
|
+
|
321
|
+
exp_list:
|
322
|
+
expression
|
323
|
+
=> [ expression ]
|
324
|
+
| exp_list ',' expression
|
325
|
+
=> exp_list << expression
|
326
|
+
;
|
327
|
+
#end-rule
|
328
|
+
%%
|
329
|
+
require 'pp'
|
330
|
+
psr = createDecoratedPL0d
|
331
|
+
t, = psr.yyparse(STDIN)
|
332
|
+
# pp t
|
333
|
+
v = Visitor.new
|
334
|
+
t.accept(v)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
const m = 7, n = 85;
|
2
|
+
var x,y;
|
3
|
+
|
4
|
+
function puts10(x)
|
5
|
+
var i;
|
6
|
+
begin
|
7
|
+
i := 0;
|
8
|
+
while i < 10 do
|
9
|
+
begin
|
10
|
+
write x; writeln;
|
11
|
+
i := i + 1;
|
12
|
+
end;
|
13
|
+
return i
|
14
|
+
end;
|
15
|
+
|
16
|
+
function fact(x)
|
17
|
+
begin
|
18
|
+
write x; writeln;
|
19
|
+
if x = 1 then return 1;
|
20
|
+
return x * fact(x - 1);
|
21
|
+
end;
|
22
|
+
|
23
|
+
begin
|
24
|
+
x := m; y := n;
|
25
|
+
write x; write y; writeln;
|
26
|
+
x := 84; y := 36;
|
27
|
+
write x; write y; writeln;
|
28
|
+
|
29
|
+
y := puts10(5);
|
30
|
+
write y; writeln;
|
31
|
+
|
32
|
+
y := fact(5);
|
33
|
+
write y; writeln;
|
34
|
+
end.
|
@@ -0,0 +1,33 @@
|
|
1
|
+
%class TinyCalc
|
2
|
+
%extend Lexer ('depager/lex.rb')
|
3
|
+
%extend Action ('depager/action.rb')
|
4
|
+
%decorate @Action
|
5
|
+
#%decorate ShiftReducePrinter ('depager/srp.rb')
|
6
|
+
%%
|
7
|
+
|
8
|
+
%LEX{
|
9
|
+
/\s+/, /\#.*/ { }
|
10
|
+
/[1-9][0-9]*/ { yield _Token(:NUM, $&.to_i) }
|
11
|
+
/./ { yield _Token($&, $&) }
|
12
|
+
%}
|
13
|
+
|
14
|
+
#begin-rule
|
15
|
+
expr :
|
16
|
+
expr '+' term { val[0] + val[2] }
|
17
|
+
| expr '-' term { val[0] - val[2] }
|
18
|
+
| term { val[0] }
|
19
|
+
;
|
20
|
+
term :
|
21
|
+
term '*' fact { val[0] * val[2] }
|
22
|
+
| term '/' fact { val[0] / val[2] }
|
23
|
+
| fact { val[0] }
|
24
|
+
;
|
25
|
+
fact :
|
26
|
+
NUM { val[0].value }
|
27
|
+
| '(' expr ')' { val[1] }
|
28
|
+
;
|
29
|
+
#end-rule
|
30
|
+
%%
|
31
|
+
parser = TinyCalc::createDecoratedParser
|
32
|
+
r, = parser.yyparse(STDIN)
|
33
|
+
puts r
|
@@ -0,0 +1,54 @@
|
|
1
|
+
%class TinyCalc
|
2
|
+
%extend Lexer ('depager/lex.rb')
|
3
|
+
%extend ASTBuilderDepthFirst ('depager/astdf.rb')
|
4
|
+
%decorate @ASTBuilderDepthFirst
|
5
|
+
#%decorate ShiftReducePrinter ('depager/srp.rb')
|
6
|
+
%%
|
7
|
+
|
8
|
+
%LEX{
|
9
|
+
/\s+/, /\#.*/ { }
|
10
|
+
/[1-9][0-9]*/ { yield _Token(:NUM, $&.to_i) }
|
11
|
+
/./ { yield _Token($&, $&) }
|
12
|
+
%}
|
13
|
+
|
14
|
+
%AST{
|
15
|
+
Node [value] { @value = nil }
|
16
|
+
Visitor { }
|
17
|
+
add(left, right) { ~value = ~left.value + ~right.value }
|
18
|
+
sub(left, right) { ~value = ~left.value - ~right.value }
|
19
|
+
mul(left, right) { ~value = ~left.value * ~right.value }
|
20
|
+
div(left, right) { ~value = ~left.value / ~right.value }
|
21
|
+
literal(-n) { ~value = ~n.value }
|
22
|
+
%}
|
23
|
+
|
24
|
+
#begin-rule
|
25
|
+
expr :
|
26
|
+
expr '+' term
|
27
|
+
=> add(expr, term)
|
28
|
+
| expr '-' term
|
29
|
+
=> sub(expr, term)
|
30
|
+
| term
|
31
|
+
=> term
|
32
|
+
;
|
33
|
+
term :
|
34
|
+
term '*' fact
|
35
|
+
=> mul(term, fact)
|
36
|
+
| term '/' fact
|
37
|
+
=> div(term, fact)
|
38
|
+
| fact
|
39
|
+
=> fact
|
40
|
+
;
|
41
|
+
fact :
|
42
|
+
NUM
|
43
|
+
=> literal(NUM)
|
44
|
+
| '(' expr ')'
|
45
|
+
=> expr
|
46
|
+
;
|
47
|
+
#end-rule
|
48
|
+
%%
|
49
|
+
require 'pp'
|
50
|
+
parser = createDecoratedTinyCalc()
|
51
|
+
t, = parser.yyparse(STDIN)
|
52
|
+
v = Visitor.new
|
53
|
+
pp t.accept(v).value
|
54
|
+
pp t
|