depager 0.2.3 → 0.3.0.b20160729
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.
- 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)
|