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.
- checksums.yaml +7 -0
- data/README.en +4 -19
- data/README.ja +42 -79
- data/bin/depager +42 -45
- data/examples/action_pl0d/pl0d.action.dr +421 -0
- data/examples/action_pl0d/test.pl0ds +49 -0
- data/examples/c89/c89.dr +493 -496
- data/examples/c89/test.c89 +10 -10
- data/examples/extension/astdf.rb +10 -0
- data/examples/extension/atree.dr +55 -0
- data/examples/{sample_calc → extension}/calc.atree.dr +42 -43
- data/examples/extension/calc.simple_action.dr +33 -0
- data/examples/extension/paction.dr +16 -15
- data/examples/extension/pactiontest.dr +14 -14
- data/examples/extension/simple_action.rb +44 -0
- data/examples/pl0d/pl0ds.dr +337 -334
- data/examples/pl0d/test.pl0ds +33 -33
- data/examples/rie_calc/calc.rie.dr +57 -0
- data/examples/rie_calc/test.calc +4 -0
- data/examples/rie_dcuse/dcuse.rie.dr +71 -0
- data/examples/rie_dcuse/test.dcuse +1 -0
- data/examples/rie_pl0/orig_ex/exerrdg.pl0 +44 -0
- data/examples/rie_pl0/orig_ex/exerrm.pl0 +19 -0
- data/examples/rie_pl0/orig_ex/exerrmre.pl0 +20 -0
- data/examples/rie_pl0/orig_ex/exerrtok.pl0 +18 -0
- data/examples/rie_pl0/orig_ex/exmdg.pl0 +40 -0
- data/examples/rie_pl0/orig_ex/exmdgwwl.pl0 +43 -0
- data/examples/rie_pl0/orig_ex/exmrw.pl0 +22 -0
- data/examples/rie_pl0/orig_ex/exmwwl.pl0 +18 -0
- data/examples/rie_pl0/orig_ex/exnorw.pl0 +17 -0
- data/examples/rie_pl0/pl0.rie.dr +450 -0
- data/examples/rie_pl0/test.pl0 +10 -0
- data/examples/sample_calc/calc.action.dr +33 -33
- data/examples/sample_calc/calc.ast.action.dr +65 -66
- data/examples/sample_calc/calc.ast.dr +55 -55
- data/examples/sample_calc/calc.cst.dr +45 -45
- data/examples/sample_calc/calc.dr +43 -43
- data/examples/sample_calc/calc.lex.dr +29 -29
- data/examples/sample_calc/{calc_prec.nvaction.dr → calc_prec.action.dr} +31 -31
- data/examples/slex_test/divreg.slex.dr +29 -29
- data/examples/slex_test/ljoin.slex.dr +36 -36
- data/examples/slex_test/test.divreg +1 -1
- data/examples/slex_test/test.ljoin +3 -3
- data/lib/depager.rb +582 -670
- data/lib/depager/grammar.rb +256 -291
- data/lib/depager/lr.rb +574 -579
- data/lib/depager/parser.rb +282 -277
- data/lib/depager/ruby/plugins/_rie_debug.rb +35 -0
- data/lib/depager/ruby/plugins/action.rb +53 -43
- data/lib/depager/ruby/plugins/ast.dr +364 -269
- data/lib/depager/ruby/plugins/ast.rb +1367 -1308
- data/lib/depager/ruby/plugins/cst.dr +172 -180
- data/lib/depager/ruby/plugins/cst.rb +587 -626
- data/lib/depager/ruby/plugins/lex.dr +85 -89
- data/lib/depager/ruby/plugins/lex.rb +310 -336
- data/lib/depager/ruby/plugins/rie.dr +723 -0
- data/lib/depager/ruby/plugins/rie.rb +1653 -0
- data/lib/depager/ruby/plugins/slex.dr +202 -200
- data/lib/depager/ruby/plugins/slex.rb +780 -817
- data/lib/depager/ruby/plugins/srp.rb +56 -51
- data/lib/depager/ruby/templates/extension_lalr_master.erb +46 -51
- data/lib/depager/ruby/templates/extension_lalr_slave.erb +99 -107
- data/lib/depager/ruby/templates/single_lalr_parser.erb +115 -117
- data/lib/depager/utils.rb +148 -318
- data/lib/depager/version.rb +4 -3
- metadata +52 -60
- data/ChangeLog +0 -16
- data/data/depager/pre-setup.rb +0 -3
- data/examples/c89/c89.tab.rb +0 -7127
- data/examples/pl0d/pl0ds.tab.rb +0 -2698
- data/examples/sample_calc/calc.action.tab.rb +0 -457
- data/examples/sample_calc/calc.ast.action.tab.rb +0 -749
- data/examples/sample_calc/calc.ast.tab.rb +0 -665
- data/examples/sample_calc/calc.astdf.dr +0 -54
- data/examples/sample_calc/calc.astdf.tab.rb +0 -672
- data/examples/sample_calc/calc.atree.tab.rb +0 -451
- data/examples/sample_calc/calc.cst.tab.rb +0 -644
- data/examples/sample_calc/calc.lex.tab.rb +0 -374
- data/examples/sample_calc/calc.nvaction.dr +0 -33
- data/examples/sample_calc/calc.nvaction.tab.rb +0 -465
- data/examples/sample_calc/calc.tab.rb +0 -365
- data/examples/sample_calc/calc_prec.nvaction.tab.rb +0 -431
- data/examples/slex_test/divreg.slex.tab.rb +0 -303
- data/examples/slex_test/ljoin.slex.tab.rb +0 -370
- data/lib/depager/ruby/plugins/_ast_tmpl.rb +0 -73
- data/lib/depager/ruby/plugins/astdf.rb +0 -6
- data/lib/depager/ruby/plugins/atree.dr +0 -55
- data/lib/depager/ruby/plugins/atree.rb +0 -347
- data/lib/depager/ruby/plugins/nvaction.rb +0 -19
- data/lib/depager/ruby/templates/simple.erb +0 -23
- data/setup.rb +0 -1585
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bb3713790063ac24f106396b593e8c6b19719cb5
|
4
|
+
data.tar.gz: e705b51cd5e659d973855d450a79e2b659c0e6a2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bbfa9bcc03b714d8a8ccfc4ea4dd1a33b6b5284031367337892f5baa4ea22818301592a61f4fedc48fe836227d67153c63bdc1c6c4a594f4f86758803d889450
|
7
|
+
data.tar.gz: 78d38d268a6897d4705babab00a96c2b61eba1bda992a507488e1f733a6f9b7af0dcce8ee20e6354a7d5ab40b9016149cbe160bc6481f9f1b2e8fcc1fedcc32a
|
data/README.en
CHANGED
@@ -7,28 +7,13 @@ Depager README
|
|
7
7
|
Requirements
|
8
8
|
------------
|
9
9
|
|
10
|
-
* Ruby
|
10
|
+
* Ruby 2.2
|
11
11
|
|
12
12
|
|
13
13
|
Install(gem)
|
14
14
|
------------
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
Install(tgz)
|
20
|
-
------------
|
21
|
-
|
22
|
-
De-compress archive and enter its top directory.
|
23
|
-
Then type:
|
24
|
-
|
25
|
-
($ su)
|
26
|
-
# ruby setup.rb
|
27
|
-
|
28
|
-
These simple step installs this program under the default
|
29
|
-
location of Ruby libraries. You can also install files into
|
30
|
-
your favorite directory by supplying setup.rb some options.
|
31
|
-
Try "ruby setup.rb --help".
|
16
|
+
$ sudo gem install depager
|
32
17
|
|
33
18
|
|
34
19
|
Usage
|
@@ -48,8 +33,8 @@ License
|
|
48
33
|
|
49
34
|
GPL
|
50
35
|
|
51
|
-
|
52
|
-
|
36
|
+
Authors
|
37
|
+
-------
|
53
38
|
|
54
39
|
maita and Nakai "Language" lab.
|
55
40
|
Hisashi Nakai(Supervisor & Original Author)
|
data/README.ja
CHANGED
@@ -1,127 +1,90 @@
|
|
1
1
|
Depager README
|
2
2
|
==============
|
3
3
|
|
4
|
-
Deager
|
4
|
+
Deagerは自己拡張可能な構文解析器生成系です。
|
5
5
|
|
6
6
|
|
7
|
-
|
7
|
+
必要環境
|
8
8
|
--------
|
9
9
|
|
10
|
-
* Ruby
|
10
|
+
* Ruby 2.2
|
11
11
|
|
12
12
|
|
13
|
-
|
13
|
+
インストール方法(gem)
|
14
14
|
---------------------
|
15
15
|
|
16
|
-
|
17
|
-
���ޥ�ɥ饤��ǰʲ��Τ褦���Ǥ�����Ǥ���������
|
16
|
+
$ sudo gem install depager
|
18
17
|
|
19
|
-
# sudo gem install depager
|
20
18
|
|
21
|
-
|
22
|
-
���ȡ�����ˡ(tgz)
|
23
|
-
---------------------
|
24
|
-
|
25
|
-
tgz��depager�Ȥ��Υ����ƥ�˥��ȡ��뤹���硢
|
26
|
-
���ޥ�ɥ饤��ǰʲ��Τ褦���Ǥ�����Ǥ���������
|
27
|
-
UNIX �� OS �ǤϤ����餯 root ���¤�ɬ�פˤʤ�ޤ���
|
28
|
-
|
29
|
-
($ su)
|
30
|
-
# ruby setup.rb
|
31
|
-
|
32
|
-
�ĿͤΥۡ���ǥ��쥯�ȥ�ʲ��˥��ȡ��뤹���硢
|
33
|
-
���ޥ�ɥ饤��ǰʲ��Τ褦���Ǥ�����Ǥ���������
|
34
|
-
|
35
|
-
# ruby setup.rb all --installdirs=home
|
36
|
-
|
37
|
-
�ĿͤΥۡ���ǥ��쥯�ȥ�ʲ��˥��ȡ��뤷����硢
|
38
|
-
�Ķ��ѿ�RUBYLIB�˥ǥ��쥯�ȥ���ɲä��Ƥ���������
|
39
|
-
(�����餯 $HOME/lib/ruby �Ǥ�)
|
40
|
-
|
41
|
-
$ RUBYLIB=$RUBYLIB:$HOME/lib/ruby
|
42
|
-
$ export RUBYLIB
|
43
|
-
|
44
|
-
���ȡ�������ѹ������ꤹ�뤳�Ȥ�Ǥ��ޤ���
|
45
|
-
���ξ��� ruby setup.rb --help ��¹Ԥ��ƤߤƤ���������
|
46
|
-
|
47
|
-
����˾ܤ���setup.rb�λȤ����ˤĤ��Ƥϡ�
|
48
|
-
setup.rb ( LoveRubyNet )
|
49
|
-
http://i.loveruby.net/ja/projects/setup/
|
50
|
-
�Ȥ��Ƥ���������
|
51
|
-
|
52
|
-
|
53
|
-
��ñ�ʻȤ���
|
19
|
+
簡単な使い方
|
54
20
|
------------
|
55
21
|
|
56
|
-
|
22
|
+
$ depager -o 出力ファイル 入力ファイル
|
57
23
|
|
58
|
-
|
24
|
+
例.
|
59
25
|
|
60
|
-
|
26
|
+
$ depager -o calc.tab.rb calc.dr
|
61
27
|
|
62
|
-
|
28
|
+
詳しくは -h オプションをご利用ください。
|
63
29
|
|
64
30
|
|
65
|
-
|
31
|
+
ファイルの簡単な説明
|
66
32
|
--------------------
|
67
33
|
|
68
34
|
/bin
|
69
|
-
depager
|
35
|
+
depager 実行用
|
70
36
|
/lib
|
71
|
-
depager.rb
|
37
|
+
depager.rb 生成系メイン
|
72
38
|
/depager
|
73
|
-
lr.rb LR
|
74
|
-
grammar.rb
|
75
|
-
utils.rb
|
76
|
-
version.rb
|
77
|
-
parser.rb
|
39
|
+
lr.rb LR表生成用
|
40
|
+
grammar.rb 解析手法定義
|
41
|
+
utils.rb 補助モジュール群
|
42
|
+
version.rb バージョン情報
|
43
|
+
parser.rb ランタイムライブラリ
|
78
44
|
/ruby
|
79
45
|
/plugins
|
80
|
-
action.rb
|
81
|
-
ast.rb AST
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
nvaction.rb ̾���ե���������ĥ
|
87
|
-
srp.rb �����å�ɽ���ǥ��졼��
|
88
|
-
slex.rb �����ջ�����ϳ�ĥ
|
46
|
+
action.rb アクション拡張
|
47
|
+
ast.rb AST拡張
|
48
|
+
cst.rb CST拡張
|
49
|
+
lex.rb 字句解析拡張
|
50
|
+
srp.rb スタック表示デコレータ
|
51
|
+
slex.rb 状態付字句解析拡張
|
89
52
|
/templetes
|
90
53
|
extension_lalr_master.erb
|
91
|
-
|
54
|
+
拡張マスタテンプレート
|
92
55
|
extension_lalr_slave.erb
|
93
|
-
|
56
|
+
拡張スレーブテンプレート
|
94
57
|
simple.rb
|
95
|
-
|
58
|
+
シンプルテンプレート
|
96
59
|
single_lalr_parser.erb
|
97
|
-
|
60
|
+
標準LRパーザテンプレート
|
98
61
|
/data
|
99
62
|
/depager
|
100
63
|
/misc
|
101
|
-
depager-mode.el Emacs
|
64
|
+
depager-mode.el Emacs用depager-mode
|
102
65
|
/examples
|
103
|
-
/c89 c89
|
104
|
-
/pl0d PL0
|
105
|
-
/extension
|
106
|
-
/samlpe_calc
|
107
|
-
/slextest
|
66
|
+
/c89 c89パーザ
|
67
|
+
/pl0d PL0インタプリタ
|
68
|
+
/extension 拡張サンプル
|
69
|
+
/samlpe_calc いろいろな電卓サンプル
|
70
|
+
/slextest 状態付字句解析拡張サンプル
|
108
71
|
|
109
72
|
|
110
|
-
|
73
|
+
ライセンス
|
111
74
|
----------
|
112
75
|
|
113
|
-
GPL
|
76
|
+
GPLに従って配布します。
|
114
77
|
|
115
78
|
|
116
|
-
|
79
|
+
その他
|
117
80
|
------
|
118
81
|
|
119
|
-
Depager
|
120
|
-
|
82
|
+
Depagerは中井央の監督のもと、maitaおよび中井
|
83
|
+
研究室によって開発されました。
|
121
84
|
|
122
|
-
Depager
|
123
|
-
|
85
|
+
Depagerの基となったDepageは同研究室の佐竹力氏によって
|
86
|
+
開発されました。
|
124
87
|
|
125
88
|
|
126
89
|
maita <maita@fujiyama.slis.tsukuba.ac.jp>
|
127
|
-
|
90
|
+
中井研究室 http://nakai2.slis.tsukuba.ac.jp/hiki/
|
data/bin/depager
CHANGED
@@ -1,45 +1,42 @@
|
|
1
|
-
#!/usr/
|
2
|
-
|
3
|
-
require '
|
4
|
-
|
5
|
-
|
6
|
-
begin
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
opt.on('-
|
13
|
-
opt.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
44
|
-
exit 1
|
45
|
-
end
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
require 'depager'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
begin
|
7
|
+
output_file_name = nil
|
8
|
+
|
9
|
+
ARGV.options do |opt|
|
10
|
+
opt.on('-v') { Depager.configuration[:verbose] = true }
|
11
|
+
opt.on('-g[FLAGS]') {|v| Depager.configuration[:debug] = v || 'sgc' }
|
12
|
+
opt.on('-o OUTPUT') {|v| output_file_name = v }
|
13
|
+
opt.parse!
|
14
|
+
end
|
15
|
+
|
16
|
+
d_parser = Depager::DeclarationPartParser.new
|
17
|
+
result = d_parser.parse(ARGV[0] ? File.open(ARGV[0]) : STDIN)
|
18
|
+
|
19
|
+
if output_file_name
|
20
|
+
File.open(output_file_name, "w"){|o| o.write result }
|
21
|
+
else
|
22
|
+
STDOUT.write result
|
23
|
+
end
|
24
|
+
rescue SystemExit
|
25
|
+
raise
|
26
|
+
rescue Exception
|
27
|
+
warn "#{File.basename $0}: fatal error."
|
28
|
+
warn "| #{$!}"
|
29
|
+
warn "| - #{d_parser.file.path}:#{d_parser.file.lineno}" if d_parser
|
30
|
+
|
31
|
+
if $@[0].match(/^(.+):(\d+)(:.+)?$/)
|
32
|
+
warn "| ( #{File.basename $1}:#{$2} )"
|
33
|
+
end
|
34
|
+
|
35
|
+
if Depager.debug_mode?
|
36
|
+
warn "#{File.basename $0}: #{$@.unshift($!).join("\n")}"
|
37
|
+
else
|
38
|
+
warn "Try -g option if you want to see more error infomation."
|
39
|
+
end
|
40
|
+
|
41
|
+
exit 1
|
42
|
+
end
|
@@ -0,0 +1,421 @@
|
|
1
|
+
%class Pl0d::Parser
|
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
|
+
%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
|
+
#begin-rule
|
39
|
+
program:
|
40
|
+
block '.'
|
41
|
+
{
|
42
|
+
debug{ warn _block.pretty_inspect }
|
43
|
+
execute(linearize_codes(_block))
|
44
|
+
}
|
45
|
+
;
|
46
|
+
|
47
|
+
block:
|
48
|
+
opt_decl_list statement
|
49
|
+
{
|
50
|
+
func = env.lookup('#FUNC#')
|
51
|
+
[
|
52
|
+
[ :O_JMP, 0, func.value ],
|
53
|
+
_opt_decl_list,
|
54
|
+
[ :O_LAB, 0, func.value ],
|
55
|
+
[ :O_INT, 0, env.max_addr-2 ],
|
56
|
+
_statement,
|
57
|
+
[ :O_RET, 0, func.argc ]
|
58
|
+
]
|
59
|
+
}
|
60
|
+
;
|
61
|
+
|
62
|
+
opt_decl_list:
|
63
|
+
{ [] }
|
64
|
+
| opt_decl_list decl
|
65
|
+
{ _opt_decl_list.concat _decl }
|
66
|
+
;
|
67
|
+
|
68
|
+
decl:
|
69
|
+
CONST const_init_list ';'
|
70
|
+
{ [ ] }
|
71
|
+
| VAR ident_list ';'
|
72
|
+
{
|
73
|
+
_ident_list.each do |ident|
|
74
|
+
not env.lookup( ident, 1 ) or
|
75
|
+
error_exit "redeclaration of variable '%s'", ident
|
76
|
+
env.install :VARIABLE, ident, nil
|
77
|
+
end
|
78
|
+
[ ]
|
79
|
+
}
|
80
|
+
| func_head block ';'
|
81
|
+
{ env.leave ; _block }
|
82
|
+
;
|
83
|
+
|
84
|
+
func_head:
|
85
|
+
FUNCTION IDENT '(' opt_ident_list ')'
|
86
|
+
{
|
87
|
+
argc = _opt_ident_list.size
|
88
|
+
lab = env.genlab
|
89
|
+
not env.lookup( _IDENT.value, 1 ) or
|
90
|
+
error_exit "redeclaration of function '%s'", _IDENT.value
|
91
|
+
env.install :FUNCTION, _IDENT.value, lab, argc
|
92
|
+
env.enter
|
93
|
+
env.install :INFO, '#FUNC#', lab, argc
|
94
|
+
_opt_ident_list.each_with_index do |ident, x|
|
95
|
+
env.install :VARIABLE, ident, x-argc
|
96
|
+
end
|
97
|
+
}
|
98
|
+
;
|
99
|
+
|
100
|
+
const_init_list:
|
101
|
+
const_init
|
102
|
+
{ }
|
103
|
+
| const_init_list ',' const_init
|
104
|
+
{ }
|
105
|
+
;
|
106
|
+
|
107
|
+
const_init:
|
108
|
+
IDENT EQ NUMBER
|
109
|
+
{
|
110
|
+
not env.lookup( _IDENT.value, 1 ) or
|
111
|
+
error_exit "redeclaration of constant '%s'", _IDENT.value
|
112
|
+
env.install :CONSTANT, _IDENT.value, _NUMBER.value
|
113
|
+
}
|
114
|
+
;
|
115
|
+
|
116
|
+
opt_ident_list:
|
117
|
+
{ [] }
|
118
|
+
| ident_list
|
119
|
+
{ _ident_list }
|
120
|
+
;
|
121
|
+
|
122
|
+
ident_list:
|
123
|
+
IDENT
|
124
|
+
{ [ _IDENT.value ] }
|
125
|
+
| ident_list ',' IDENT
|
126
|
+
{ _ident_list << _IDENT.value }
|
127
|
+
;
|
128
|
+
|
129
|
+
statement:
|
130
|
+
{ [] }
|
131
|
+
| IDENT COLOEQ expression
|
132
|
+
{
|
133
|
+
entry = env.lookup( _IDENT.value )
|
134
|
+
entry or
|
135
|
+
error_exit "undeclared identifier %s", _IDENT.value
|
136
|
+
entry.kind == :VARIABLE or
|
137
|
+
error_exit "assignment to constant/procedure is not allowed"
|
138
|
+
[
|
139
|
+
_expression,
|
140
|
+
[ :O_STO, env.level - entry.level, entry.value ]
|
141
|
+
]
|
142
|
+
}
|
143
|
+
| BEGINN state_list END
|
144
|
+
{
|
145
|
+
_state_list
|
146
|
+
}
|
147
|
+
| IF condition THEN statement
|
148
|
+
{
|
149
|
+
lab = env.genlab();
|
150
|
+
[
|
151
|
+
_condition,
|
152
|
+
[ :O_JPC, 0, lab ],
|
153
|
+
_statement,
|
154
|
+
[ :O_LAB, 0, lab ]
|
155
|
+
]
|
156
|
+
}
|
157
|
+
| WHILE condition DO statement
|
158
|
+
{
|
159
|
+
lab1 = env.genlab()
|
160
|
+
lab2 = env.genlab()
|
161
|
+
[
|
162
|
+
[ :O_LAB, 0, lab1 ],
|
163
|
+
_condition,
|
164
|
+
[ :O_JPC, 0, lab2 ],
|
165
|
+
_statement,
|
166
|
+
[ :O_JMP, 0, lab1 ],
|
167
|
+
[ :O_LAB, 0, lab2 ]
|
168
|
+
]
|
169
|
+
}
|
170
|
+
| RETURN expression
|
171
|
+
{
|
172
|
+
[
|
173
|
+
_expression,
|
174
|
+
[ :O_RET, 0, env.lookup('#FUNC#').argc ]
|
175
|
+
]
|
176
|
+
}
|
177
|
+
| WRITE expression
|
178
|
+
{
|
179
|
+
[
|
180
|
+
_expression,
|
181
|
+
[ :O_OPR, 0, :P_WRI ]
|
182
|
+
]
|
183
|
+
}
|
184
|
+
| WRITELN
|
185
|
+
{ [ [ :O_OPR, 0, :P_WRL ] ] }
|
186
|
+
;
|
187
|
+
|
188
|
+
state_list:
|
189
|
+
statement
|
190
|
+
{ [ _statement ] }
|
191
|
+
| state_list ';' statement
|
192
|
+
{ _state_list << _statement }
|
193
|
+
;
|
194
|
+
|
195
|
+
condition:
|
196
|
+
ODD expression
|
197
|
+
{ [ _expression, [ :O_OPR, 0, :P_ODD ] ] }
|
198
|
+
| expression-e0 EQ expression-e1
|
199
|
+
{ [ _e0, _e1, [ :O_OPR, 0, :P_EQ ] ] }
|
200
|
+
| expression-e0 NOTEQ expression-e1
|
201
|
+
{ [ _e0, _e1, [ :O_OPR, 0, :P_NE ] ] }
|
202
|
+
| expression-e0 LT expression-e1
|
203
|
+
{ [ _e0, _e1, [ :O_OPR, 0, :P_LT ] ] }
|
204
|
+
| expression-e0 GT expression-e1
|
205
|
+
{ [ _e0, _e1, [ :O_OPR, 0, :P_GT ] ] }
|
206
|
+
| expression-e0 LE expression-e1
|
207
|
+
{ [ _e0, _e1, [ :O_OPR, 0, :P_LE ] ] }
|
208
|
+
| expression-e0 GE expression-e1
|
209
|
+
{ [ _e0, _e1, [ :O_OPR, 0, :P_GE ] ] }
|
210
|
+
;
|
211
|
+
|
212
|
+
expression:
|
213
|
+
expression '+' term
|
214
|
+
{ [ _expression, _term, [ :O_OPR, 0, :P_ADD ] ] }
|
215
|
+
| expression '-' term
|
216
|
+
{ [ _expression, _term, [ :O_OPR, 0, :P_SUB ] ] }
|
217
|
+
| term
|
218
|
+
{ _term }
|
219
|
+
| '-' term
|
220
|
+
{ [ _term, [ :O_OPR, 0, :P_NEG ] ] }
|
221
|
+
;
|
222
|
+
|
223
|
+
term:
|
224
|
+
term '*' factor
|
225
|
+
{ [ _term, _factor, [ :O_OPR, 0, :P_MUL ] ] }
|
226
|
+
| term '/' factor
|
227
|
+
{ [ _term, _factor, [ :O_OPR, 0, :P_DIV ] ] }
|
228
|
+
| factor
|
229
|
+
{ _factor }
|
230
|
+
;
|
231
|
+
|
232
|
+
factor:
|
233
|
+
IDENT
|
234
|
+
{
|
235
|
+
entry = env.lookup( _IDENT.value )
|
236
|
+
entry or
|
237
|
+
error_exit "undeclared identifier %s", _IDENT.value
|
238
|
+
entry.kind != :FUNCTION or
|
239
|
+
error_exit "expression must not contain a procedure identifier"
|
240
|
+
entry.kind == :CONSTANT ?
|
241
|
+
[ :O_LIT, 0, entry.value ] :
|
242
|
+
[ :O_LOD, env.level - entry.level, entry.value ]
|
243
|
+
}
|
244
|
+
| NUMBER
|
245
|
+
{ [ :O_LIT, 0, _NUMBER.value ] }
|
246
|
+
| IDENT '(' opt_exp_list ')'
|
247
|
+
{
|
248
|
+
entry = env.lookup( _IDENT.value )
|
249
|
+
entry or
|
250
|
+
error_exit "undeclared identifier %s", _IDENT.value
|
251
|
+
entry.kind == :FUNCTION or
|
252
|
+
error_exit "call of a constant or a variable is meaningless"
|
253
|
+
entry.argc == _opt_exp_list.size or
|
254
|
+
error_exit "wrong number of arguments %i for %i", _opt_exp_list.size, entry.argc
|
255
|
+
[
|
256
|
+
_opt_exp_list,
|
257
|
+
[ :O_CAL, env.level - entry.level, entry.value ]
|
258
|
+
]
|
259
|
+
}
|
260
|
+
| '(' expression ')'
|
261
|
+
{ _expression }
|
262
|
+
;
|
263
|
+
|
264
|
+
opt_exp_list:
|
265
|
+
{ [] }
|
266
|
+
| exp_list
|
267
|
+
{ _exp_list }
|
268
|
+
;
|
269
|
+
|
270
|
+
exp_list:
|
271
|
+
expression
|
272
|
+
{ [ _expression ] }
|
273
|
+
| exp_list ',' expression
|
274
|
+
{ _exp_list << _expression }
|
275
|
+
;
|
276
|
+
#end-rule
|
277
|
+
%%
|
278
|
+
|
279
|
+
class Pl0d::Action
|
280
|
+
class Entry
|
281
|
+
attr_accessor :kind, :name, :value, :argc, :level
|
282
|
+
|
283
|
+
def initialize k, n, v, c, l
|
284
|
+
@kind, @name, @value, @argc, @level = k, n, v, c, l
|
285
|
+
end
|
286
|
+
def inspect
|
287
|
+
"(#{@name}.#{@level}:#{@kind.to_s[0,1]}[#{@argc}]/#{@value})"
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
class Env
|
292
|
+
def initialize
|
293
|
+
@stack, @label = [], 0
|
294
|
+
end
|
295
|
+
def enter
|
296
|
+
@stack.push({})
|
297
|
+
end
|
298
|
+
def leave
|
299
|
+
@stack.pop
|
300
|
+
end
|
301
|
+
def level
|
302
|
+
@stack.size-1
|
303
|
+
end
|
304
|
+
def install k, n, v, c = 0
|
305
|
+
v ||= max_addr+1
|
306
|
+
@stack.last[n] = Entry.new(k, n, v, c, level)
|
307
|
+
end
|
308
|
+
def lookup name, n = nil
|
309
|
+
return nil if @stack.empty?
|
310
|
+
n ||= @stack.size
|
311
|
+
(1 .. n).each do |x|
|
312
|
+
result = @stack[-x][name] and
|
313
|
+
return result
|
314
|
+
end
|
315
|
+
return nil
|
316
|
+
end
|
317
|
+
def max_addr
|
318
|
+
# 3 local variables are reserved(BP+0,BP+1,BP+2).
|
319
|
+
max = @stack.last.select{|k,v| v.kind==:VARIABLE }.map{|k,v| v.value}.max.to_i
|
320
|
+
max < 2 ? 2 : max
|
321
|
+
end
|
322
|
+
def genlab
|
323
|
+
@label += 1
|
324
|
+
end
|
325
|
+
def inspect
|
326
|
+
result = "LEVEL:#{level}\n"
|
327
|
+
@stack.reverse.each_with_index do |i,x|
|
328
|
+
result << "(#{level-x}):#{i.inspect}\n"
|
329
|
+
end
|
330
|
+
result
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
attr_reader :env
|
335
|
+
def initialize inside
|
336
|
+
super
|
337
|
+
@env = Env.new
|
338
|
+
env.enter ; env.install :CONSTANT, "#FUNC#", env.genlab, 0
|
339
|
+
end
|
340
|
+
def error_exit *args
|
341
|
+
print("#{basis.file.lineno}:")
|
342
|
+
printf(*args); print "\n"; exit
|
343
|
+
end
|
344
|
+
def debug
|
345
|
+
yield if $DEBUG
|
346
|
+
end
|
347
|
+
def linearize_codes codes, res=[], labs={}
|
348
|
+
codes.each do |i|
|
349
|
+
i.is_a? Array or
|
350
|
+
raise "invalid code"
|
351
|
+
case i[0]
|
352
|
+
when :O_LAB
|
353
|
+
lab, addr = i[2], res.size
|
354
|
+
debug{ warn "LABEL: L#{lab}->##{addr} BACKPATCH: #{labs[lab].inspect}" }
|
355
|
+
labs[lab] and labs[lab].each{|i| res[i][2] = addr }
|
356
|
+
labs[lab] = res.size
|
357
|
+
when :O_JMP, :O_JPC, :O_CAL
|
358
|
+
lab, addr = i[2], labs[i[2]]
|
359
|
+
if addr.is_a? Integer
|
360
|
+
i[2] = addr
|
361
|
+
else
|
362
|
+
labs[lab] ||= []
|
363
|
+
labs[lab] << res.size
|
364
|
+
end
|
365
|
+
res << i
|
366
|
+
when Symbol
|
367
|
+
res << i
|
368
|
+
else
|
369
|
+
linearize_codes i, res, labs
|
370
|
+
end
|
371
|
+
end ; res
|
372
|
+
end
|
373
|
+
# *STACK* :-3(BP) :-2 :-1
|
374
|
+
# {...args...}[lexical base][old BP][old PC]{...vars...}
|
375
|
+
def execute codes
|
376
|
+
debug{
|
377
|
+
warn "\n** CODES **"
|
378
|
+
codes.each_with_index{|i,x| warn "#{'% 4i'%x} #{i.inspect}"}
|
379
|
+
warn "\n** EXEC **"
|
380
|
+
}
|
381
|
+
pc, bp, s = 0, 1, [0, 0, 0, 0]
|
382
|
+
begin
|
383
|
+
pc < codes.size or
|
384
|
+
raise "ADDRESS ERROR(PC:#{pc})."
|
385
|
+
op, l, a = codes[pc] ; pc += 1
|
386
|
+
debug{ warn " #{s.inspect}\nPC:#{pc-1} BP:#{bp} CODE:[#{op}, #{l}, #{a}]" }
|
387
|
+
case op
|
388
|
+
when :O_LIT; s.push a
|
389
|
+
when :O_OPR;
|
390
|
+
case a
|
391
|
+
when :P_NEG; s.push(-s.pop)
|
392
|
+
when :P_ODD; s.push s.pop % 2
|
393
|
+
when :P_ADD; r=s.pop; s.push s.pop + r
|
394
|
+
when :P_SUB; r=s.pop; s.push s.pop - r
|
395
|
+
when :P_MUL; r=s.pop; s.push s.pop * r
|
396
|
+
when :P_DIV; r=s.pop; s.push s.pop / r
|
397
|
+
when :P_EQ ; r=s.pop; s.push( s.pop == r ? 1 : 0 )
|
398
|
+
when :P_NE ; r=s.pop; s.push( s.pop != r ? 1 : 0 )
|
399
|
+
when :P_LT ; r=s.pop; s.push( s.pop < r ? 1 : 0 )
|
400
|
+
when :P_GE ; r=s.pop; s.push( s.pop >= r ? 1 : 0 )
|
401
|
+
when :P_GT ; r=s.pop; s.push( s.pop > r ? 1 : 0 )
|
402
|
+
when :P_LE ; r=s.pop; s.push( s.pop <= r ? 1 : 0 )
|
403
|
+
when :P_RDI; print "?"; s.push Integer(STDIN.gets)
|
404
|
+
when :P_WRI; printf( "\t%10d", s.pop )
|
405
|
+
when :P_WRL; puts ""
|
406
|
+
end
|
407
|
+
when :O_INT; s.fill(0, s.size, a)
|
408
|
+
when :O_LOD; x=bp;l.times{x=s[x]}; s.push s[x+a];
|
409
|
+
when :O_STO; x=bp;l.times{x=s[x]}; s[x+a] = s.pop;
|
410
|
+
when :O_CAL; x=bp;l.times{x=s[x]}; s.push x, bp, pc; bp, pc = s.size-3, a;
|
411
|
+
when :O_RET; r=s.pop; _, bp, pc, = s.slice!(bp..-1); s.slice!(-a, a) ; s.push r
|
412
|
+
when :O_JMP; pc = a
|
413
|
+
when :O_JPC; pc = a if s.pop == 0
|
414
|
+
end
|
415
|
+
end while pc != 0
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
require 'pp'
|
420
|
+
parser = Pl0d.create_decorated_parser
|
421
|
+
r, = parser.parse(STDIN)
|