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
@@ -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)