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.
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
@@ -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 1.8
10
+ * Ruby 2.2
11
11
 
12
12
 
13
13
  Install(gem)
14
14
  ------------
15
15
 
16
- $ sudo gem install depager
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
- Author
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 1.8
10
+ * Ruby 2.2
11
11
 
12
12
 
13
- ���󥹥ȡ�����ˡ(gem)
13
+ インストール方法(gem)
14
14
  ---------------------
15
15
 
16
- gem��depager�򤪻Ȥ��Υ����ƥ�˥��󥹥ȡ��뤹���硢
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
- # depager -o ���ϥե����� ���ϥե�����
22
+ $ depager -o 出力ファイル 入力ファイル
57
23
 
58
- ��.
24
+ 例.
59
25
 
60
- # depager -o calc.tab.rb calc.dr
26
+ $ depager -o calc.tab.rb calc.dr
61
27
 
62
- �ܤ����� -h ���ץ��������Ѥ���������
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
- astdf.rb ����ͥ��õ��AST��ĥ
83
- atree.rb ����ˤ���ڹ��۳�ĥ
84
- cst.rb CST��ĥ
85
- lex.rb ������ϳ�ĥ
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
- ɸ��LR�ѡ����ƥ�ץ졼��
60
+ 標準LRパーザテンプレート
98
61
  /data
99
62
  /depager
100
63
  /misc
101
- depager-mode.el Emacs��depager-mode
64
+ depager-mode.el Emacsdepager-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�������δ��ĤΤ�ȡ�maita��������
120
- ���漼�ˤ�äƳ�ȯ����ޤ�����
82
+ Depagerは中井央の監督のもと、maitaおよび中井
83
+ 研究室によって開発されました。
121
84
 
122
- Depager�δ�Ȥʤä�Depage��Ʊ���漼�κ����ϻ�ˤ�ä�
123
- ��ȯ����ޤ�����
85
+ Depagerの基となったDepageは同研究室の佐竹力氏によって
86
+ 開発されました。
124
87
 
125
88
 
126
89
  maita <maita@fujiyama.slis.tsukuba.ac.jp>
127
- ��渦�漼 http://nakai2.slis.tsukuba.ac.jp/hiki/
90
+ 中井研究室 http://nakai2.slis.tsukuba.ac.jp/hiki/
@@ -1,45 +1,42 @@
1
- #!/usr/local/bin/ruby
2
- require 'depager'
3
- require 'optparse'
4
-
5
- include Depager
6
- begin
7
- $MP_VERBOSE = nil
8
- $MP_DEBUG = nil
9
- dp = nil
10
- output_file_name = nil
11
- ARGV.options do |opt|
12
- opt.on('-v') { $MP_VERBOSE = true }
13
- opt.on('-g[FLAGS]') {|flags| $MP_DEBUG = flags || 'sgc' }
14
- opt.on('-o OUTPUT') {|ofn| output_file_name = ofn }
15
- opt.parse!
16
- end
17
-
18
- f = ARGV[0] ? File.open(ARGV[0]) : STDIN
19
- begin
20
- dp = DeclParser.new
21
- res = dp.parse(f, ARGV[0])
22
- if output_file_name
23
- File.open(output_file_name, "w"){|o| o.write res }
24
- else
25
- print res
26
- end
27
- rescue Exception
28
- lineno = dp.files.lineno rescue '?'
29
- raise
30
- end
31
- rescue SystemExit
32
- raise
33
- rescue Exception
34
- warn "#{File.basename $0}: fatal error."
35
- warn "| #{$!}"
36
- warn "| - #{dp.files.path}:#{lineno}" if dp
37
- $@[0].match(/^(.+):(\d+)(:.+)?$/)
38
- warn "| ( #{File.basename $1}:#{$2} )"
39
- if $MP_DEBUG
40
- warn "#{File.basename $0}: #{$@.unshift($!).join("\n")}"
41
- else
42
- warn "Try -g option if you want to see more error infomation."
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)