depager 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|