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