rltk 2.2.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +12 -12
- data/README.md +458 -285
- data/Rakefile +99 -92
- data/lib/rltk/ast.rb +221 -126
- data/lib/rltk/cfg.rb +218 -239
- data/lib/rltk/cg/basic_block.rb +1 -1
- data/lib/rltk/cg/bindings.rb +9 -26
- data/lib/rltk/cg/builder.rb +40 -8
- data/lib/rltk/cg/context.rb +1 -1
- data/lib/rltk/cg/contractor.rb +51 -0
- data/lib/rltk/cg/execution_engine.rb +45 -8
- data/lib/rltk/cg/function.rb +12 -2
- data/lib/rltk/cg/generated_bindings.rb +2541 -575
- data/lib/rltk/cg/generic_value.rb +2 -2
- data/lib/rltk/cg/instruction.rb +104 -83
- data/lib/rltk/cg/llvm.rb +44 -3
- data/lib/rltk/cg/memory_buffer.rb +22 -5
- data/lib/rltk/cg/module.rb +85 -36
- data/lib/rltk/cg/old_generated_bindings.rb +6152 -0
- data/lib/rltk/cg/pass_manager.rb +87 -43
- data/lib/rltk/cg/support.rb +2 -4
- data/lib/rltk/cg/target.rb +158 -28
- data/lib/rltk/cg/triple.rb +8 -8
- data/lib/rltk/cg/type.rb +69 -25
- data/lib/rltk/cg/value.rb +107 -66
- data/lib/rltk/cg.rb +16 -17
- data/lib/rltk/lexer.rb +21 -11
- data/lib/rltk/lexers/calculator.rb +1 -1
- data/lib/rltk/lexers/ebnf.rb +8 -7
- data/lib/rltk/parser.rb +300 -247
- data/lib/rltk/parsers/infix_calc.rb +1 -1
- data/lib/rltk/parsers/postfix_calc.rb +2 -2
- data/lib/rltk/parsers/prefix_calc.rb +2 -2
- data/lib/rltk/token.rb +1 -2
- data/lib/rltk/version.rb +3 -3
- data/lib/rltk.rb +6 -6
- data/test/cg/tc_basic_block.rb +83 -0
- data/test/cg/tc_control_flow.rb +191 -0
- data/test/cg/tc_function.rb +54 -0
- data/test/cg/tc_generic_value.rb +33 -0
- data/test/cg/tc_instruction.rb +256 -0
- data/test/cg/tc_llvm.rb +25 -0
- data/test/cg/tc_math.rb +88 -0
- data/test/cg/tc_module.rb +89 -0
- data/test/cg/tc_transforms.rb +68 -0
- data/test/cg/tc_type.rb +69 -0
- data/test/cg/tc_value.rb +151 -0
- data/test/cg/ts_cg.rb +23 -0
- data/test/tc_ast.rb +105 -8
- data/test/tc_cfg.rb +63 -48
- data/test/tc_lexer.rb +84 -96
- data/test/tc_parser.rb +224 -52
- data/test/tc_token.rb +6 -6
- data/test/ts_rltk.rb +12 -15
- metadata +149 -75
- data/lib/rltk/cg/generated_extended_bindings.rb +0 -287
- data/lib/rltk/util/abstract_class.rb +0 -25
- data/lib/rltk/util/monkeys.rb +0 -129
data/test/tc_cfg.rb
CHANGED
@@ -7,8 +7,8 @@
|
|
7
7
|
# Requires #
|
8
8
|
############
|
9
9
|
|
10
|
-
#
|
11
|
-
require '
|
10
|
+
# Gems
|
11
|
+
require 'minitest/autorun'
|
12
12
|
|
13
13
|
# Ruby Language Toolkit
|
14
14
|
require 'rltk/cfg'
|
@@ -17,7 +17,7 @@ require 'rltk/cfg'
|
|
17
17
|
# Classes and Modules #
|
18
18
|
#######################
|
19
19
|
|
20
|
-
class CFGTester < Test
|
20
|
+
class CFGTester < Minitest::Test
|
21
21
|
def setup
|
22
22
|
@grammar = RLTK::CFG.new
|
23
23
|
|
@@ -35,59 +35,74 @@ class CFGTester < Test::Unit::TestCase
|
|
35
35
|
def test_callback
|
36
36
|
grammar = RLTK::CFG.new
|
37
37
|
|
38
|
-
|
39
|
-
grammar.callback do |
|
40
|
-
|
41
|
-
assert_equal(type, :
|
38
|
+
call_count = 0
|
39
|
+
grammar.callback do |type, which, p|
|
40
|
+
refute_nil(p)
|
41
|
+
assert_equal(type, :optional)
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
else
|
47
|
-
assert_equal(num, :second)
|
43
|
+
case call_count
|
44
|
+
when 0 then assert_equal(:empty, which)
|
45
|
+
when 1 then assert_equal(:nonempty, which)
|
48
46
|
end
|
47
|
+
|
48
|
+
call_count += 1
|
49
49
|
end
|
50
50
|
|
51
51
|
grammar.production(:a, 'A?') { |a| a }
|
52
|
+
assert_equal(2, call_count)
|
52
53
|
|
53
|
-
|
54
|
-
grammar.callback do |
|
55
|
-
|
56
|
-
assert_equal(type, :*)
|
54
|
+
call_count = 0
|
55
|
+
grammar.callback do |type, which, p|
|
56
|
+
refute_nil(p)
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
case call_count
|
59
|
+
when 0
|
60
|
+
assert_equal(:elp, type)
|
61
|
+
assert_equal(:empty, which)
|
62
|
+
|
63
|
+
when 1
|
64
|
+
assert_equal(:elp, type)
|
65
|
+
assert_equal(:nonempty, which)
|
66
|
+
|
67
|
+
when 2
|
68
|
+
assert_equal(:nelp, type)
|
69
|
+
assert_equal(:single, which)
|
70
|
+
|
71
|
+
when 3
|
72
|
+
assert_equal(:nelp, type)
|
73
|
+
assert_equal(:multiple, which)
|
63
74
|
end
|
75
|
+
|
76
|
+
call_count += 1
|
64
77
|
end
|
65
78
|
|
66
79
|
grammar.production(:a, 'A*') { |a| a }
|
80
|
+
assert_equal(4, call_count)
|
67
81
|
|
68
|
-
|
69
|
-
grammar.callback do |
|
70
|
-
|
71
|
-
assert_equal(type,
|
82
|
+
call_count = 0
|
83
|
+
grammar.callback do |type, which, p|
|
84
|
+
refute_nil(p)
|
85
|
+
assert_equal(type, :nelp)
|
72
86
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
else
|
77
|
-
assert_equal(num, :second)
|
87
|
+
case call_count
|
88
|
+
when 0 then assert_equal(:single, which)
|
89
|
+
when 1 then assert_equal(:multiple, which)
|
78
90
|
end
|
91
|
+
|
92
|
+
call_count += 1
|
79
93
|
end
|
80
94
|
|
81
95
|
grammar.production(:a, 'A+') { |a| a }
|
96
|
+
assert_equal(2, call_count)
|
82
97
|
end
|
83
98
|
|
84
99
|
def test_first_set
|
85
100
|
@grammar.first_set(:s).each do |sym|
|
86
|
-
|
101
|
+
assert_includes([:A, :B], sym)
|
87
102
|
end
|
88
103
|
|
89
|
-
assert_equal(@grammar.first_set(:b)
|
90
|
-
assert_equal(@grammar.first_set(:a)
|
104
|
+
assert_equal([:G], @grammar.first_set(:b))
|
105
|
+
assert_equal([:G], @grammar.first_set(:a))
|
91
106
|
end
|
92
107
|
|
93
108
|
def test_follow_set
|
@@ -103,13 +118,13 @@ class CFGTester < Test::Unit::TestCase
|
|
103
118
|
end
|
104
119
|
|
105
120
|
def test_is_nonterminal
|
106
|
-
|
107
|
-
|
121
|
+
assert(RLTK::CFG::is_nonterminal?(:lowercase))
|
122
|
+
assert(!RLTK::CFG::is_nonterminal?(:UPERCASE))
|
108
123
|
end
|
109
124
|
|
110
125
|
def test_is_terminal
|
111
|
-
|
112
|
-
|
126
|
+
assert(!RLTK::CFG::is_terminal?(:lowercase))
|
127
|
+
assert(RLTK::CFG::is_terminal?(:UPERCASE))
|
113
128
|
end
|
114
129
|
|
115
130
|
def test_item
|
@@ -117,25 +132,25 @@ class CFGTester < Test::Unit::TestCase
|
|
117
132
|
i1 = i0.copy
|
118
133
|
|
119
134
|
assert_equal(i0, i1)
|
120
|
-
|
121
|
-
assert_equal(i0.next_symbol
|
135
|
+
assert(!i0.at_end?)
|
136
|
+
assert_equal(:b, i0.next_symbol)
|
122
137
|
|
123
138
|
i0.advance
|
124
139
|
|
125
|
-
|
126
|
-
|
127
|
-
assert_equal(i0.next_symbol
|
140
|
+
refute_equal(i0, i1)
|
141
|
+
assert(!i0.at_end?)
|
142
|
+
assert_equal(:C, i0.next_symbol)
|
128
143
|
|
129
144
|
i0.advance
|
130
|
-
|
131
|
-
assert_equal(i0.next_symbol
|
145
|
+
assert(!i0.at_end?)
|
146
|
+
assert_equal(:D, i0.next_symbol)
|
132
147
|
|
133
148
|
i0.advance
|
134
|
-
|
135
|
-
assert_equal(i0.next_symbol
|
149
|
+
assert(!i0.at_end?)
|
150
|
+
assert_equal(:e, i0.next_symbol)
|
136
151
|
|
137
152
|
i0.advance
|
138
|
-
|
153
|
+
assert(i0.at_end?)
|
139
154
|
assert_nil(i0.next_symbol)
|
140
155
|
end
|
141
156
|
|
@@ -144,6 +159,6 @@ class CFGTester < Test::Unit::TestCase
|
|
144
159
|
p1 = p0.copy
|
145
160
|
|
146
161
|
assert_equal(p0, p1)
|
147
|
-
assert_equal(p0.last_terminal
|
162
|
+
assert_equal(:D, p0.last_terminal)
|
148
163
|
end
|
149
164
|
end
|
data/test/tc_lexer.rb
CHANGED
@@ -7,8 +7,8 @@
|
|
7
7
|
# Requires #
|
8
8
|
############
|
9
9
|
|
10
|
-
#
|
11
|
-
require '
|
10
|
+
# Gems
|
11
|
+
require 'minitest/autorun'
|
12
12
|
|
13
13
|
# Ruby Language Toolkit
|
14
14
|
require 'rltk/token'
|
@@ -20,21 +20,21 @@ require 'rltk/lexers/ebnf'
|
|
20
20
|
# Classes and Modules #
|
21
21
|
#######################
|
22
22
|
|
23
|
-
class LexerTester < Test
|
23
|
+
class LexerTester < Minitest::Test
|
24
24
|
class ABLongest < RLTK::Lexer
|
25
|
-
rule(/a+/)
|
26
|
-
rule(/b+/)
|
25
|
+
rule(/a+/) { :APLUS }
|
26
|
+
rule(/b+/) { :BPLUS }
|
27
27
|
|
28
|
-
rule(/a+b+/)
|
28
|
+
rule(/a+b+/) { :APLUSBPLUS }
|
29
29
|
end
|
30
30
|
|
31
31
|
class ABFirst < RLTK::Lexer
|
32
32
|
match_first
|
33
33
|
|
34
|
-
rule(/a+/)
|
35
|
-
rule(/b+/)
|
34
|
+
rule(/a+/) { :APLUS }
|
35
|
+
rule(/b+/) { :BPLUS }
|
36
36
|
|
37
|
-
rule(/a+b+/)
|
37
|
+
rule(/a+b+/) { :APLUSBPLUS }
|
38
38
|
end
|
39
39
|
|
40
40
|
class ENVLexer < RLTK::Lexer
|
@@ -53,21 +53,21 @@ class LexerTester < Test::Unit::TestCase
|
|
53
53
|
end
|
54
54
|
|
55
55
|
class FlagLexer < RLTK::Lexer
|
56
|
-
rule(/a/)
|
56
|
+
rule(/a/) { set_flag(:a); :A }
|
57
57
|
rule(/\s/)
|
58
58
|
|
59
|
-
rule(/b/, :default, [:a])
|
60
|
-
rule(/c/, :default, [:a, :b])
|
59
|
+
rule(/b/, :default, [:a]) { set_flag(:b); :B }
|
60
|
+
rule(/c/, :default, [:a, :b]) { :C }
|
61
61
|
end
|
62
62
|
|
63
63
|
class StateLexer < RLTK::Lexer
|
64
|
-
rule(/a/)
|
64
|
+
rule(/a/) { :A }
|
65
65
|
rule(/\s/)
|
66
66
|
|
67
|
-
rule(/\(\*/)
|
67
|
+
rule(/\(\*/) { push_state(:comment) }
|
68
68
|
|
69
|
-
rule(/\(\*/, :comment)
|
70
|
-
rule(/\*\)/, :comment)
|
69
|
+
rule(/\(\*/, :comment) { push_state(:comment) }
|
70
|
+
rule(/\*\)/, :comment) { pop_state }
|
71
71
|
rule(/./, :comment)
|
72
72
|
end
|
73
73
|
|
@@ -76,19 +76,18 @@ class LexerTester < Test::Unit::TestCase
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def test_calc
|
79
|
-
expected =
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
]
|
79
|
+
expected = [
|
80
|
+
RLTK::Token.new(:NUM, 1),
|
81
|
+
|
82
|
+
RLTK::Token.new(:PLS),
|
83
|
+
RLTK::Token.new(:SUB),
|
84
|
+
RLTK::Token.new(:MUL),
|
85
|
+
RLTK::Token.new(:DIV),
|
86
|
+
|
87
|
+
RLTK::Token.new(:LPAREN),
|
88
|
+
RLTK::Token.new(:RPAREN),
|
89
|
+
RLTK::Token.new(:EOS)
|
90
|
+
]
|
92
91
|
|
93
92
|
actual = RLTK::Lexers::Calculator.lex('1 + - * / ( )')
|
94
93
|
|
@@ -96,16 +95,15 @@ class LexerTester < Test::Unit::TestCase
|
|
96
95
|
end
|
97
96
|
|
98
97
|
def test_ebnf
|
99
|
-
expected =
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
]
|
98
|
+
expected = [
|
99
|
+
RLTK::Token.new(:NONTERM, :aaa),
|
100
|
+
RLTK::Token.new(:TERM, :BBB),
|
101
|
+
|
102
|
+
RLTK::Token.new(:STAR),
|
103
|
+
RLTK::Token.new(:PLUS),
|
104
|
+
RLTK::Token.new(:QUESTION),
|
105
|
+
RLTK::Token.new(:EOS)
|
106
|
+
]
|
109
107
|
|
110
108
|
actual = RLTK::Lexers::EBNF.lex('aaa BBB * + ?')
|
111
109
|
|
@@ -113,13 +111,12 @@ class LexerTester < Test::Unit::TestCase
|
|
113
111
|
end
|
114
112
|
|
115
113
|
def test_environment
|
116
|
-
expected =
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
]
|
114
|
+
expected = [
|
115
|
+
RLTK::Token.new(:A, 0),
|
116
|
+
RLTK::Token.new(:A, 1),
|
117
|
+
RLTK::Token.new(:A, 2),
|
118
|
+
RLTK::Token.new(:EOS)
|
119
|
+
]
|
123
120
|
|
124
121
|
actual = ENVLexer.lex('aaa')
|
125
122
|
|
@@ -129,24 +126,22 @@ class LexerTester < Test::Unit::TestCase
|
|
129
126
|
|
130
127
|
assert_equal(expected, lexer.lex('aaa'))
|
131
128
|
|
132
|
-
expected =
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
]
|
129
|
+
expected = [
|
130
|
+
RLTK::Token.new(:A, 3),
|
131
|
+
RLTK::Token.new(:A, 4),
|
132
|
+
RLTK::Token.new(:A, 5),
|
133
|
+
RLTK::Token.new(:EOS)
|
134
|
+
]
|
139
135
|
|
140
136
|
assert_equal(expected, lexer.lex('aaa'))
|
141
137
|
end
|
142
138
|
|
143
139
|
def test_first_match
|
144
|
-
expected =
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
]
|
140
|
+
expected = [
|
141
|
+
RLTK::Token.new(:APLUS),
|
142
|
+
RLTK::Token.new(:BPLUS),
|
143
|
+
RLTK::Token.new(:EOS)
|
144
|
+
]
|
150
145
|
|
151
146
|
actual = ABFirst.lex('aaabbb')
|
152
147
|
|
@@ -155,49 +150,43 @@ class LexerTester < Test::Unit::TestCase
|
|
155
150
|
|
156
151
|
def test_flags
|
157
152
|
|
158
|
-
|
159
|
-
|
153
|
+
assert_raises(RLTK::LexingError) { FlagLexer.lex('b') }
|
154
|
+
assert_raises(RLTK::LexingError) { FlagLexer.lex('ac') }
|
160
155
|
|
161
|
-
expected =
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
]
|
156
|
+
expected = [
|
157
|
+
RLTK::Token.new(:A),
|
158
|
+
RLTK::Token.new(:B),
|
159
|
+
RLTK::Token.new(:C),
|
160
|
+
RLTK::Token.new(:EOS)
|
161
|
+
]
|
168
162
|
|
169
163
|
actual = FlagLexer.lex('abc')
|
170
164
|
assert_equal(expected, actual)
|
171
165
|
|
172
|
-
expected =
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
]
|
166
|
+
expected = [
|
167
|
+
RLTK::Token.new(:A),
|
168
|
+
RLTK::Token.new(:B),
|
169
|
+
RLTK::Token.new(:C),
|
170
|
+
RLTK::Token.new(:A),
|
171
|
+
RLTK::Token.new(:B),
|
172
|
+
RLTK::Token.new(:C),
|
173
|
+
RLTK::Token.new(:EOS)
|
174
|
+
]
|
182
175
|
|
183
176
|
actual = FlagLexer.lex('abcabc')
|
184
177
|
assert_equal(expected, actual)
|
185
178
|
end
|
186
179
|
|
187
180
|
def test_lex
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
assert_nothing_raised(RLTK::LexingError) { ABFirst.lex('aaabbb') }
|
192
|
-
assert_nothing_raised(RLTK::LexingError) { ABLongest.lex('aaabbb') }
|
181
|
+
assert_raises(RLTK::LexingError) { ABFirst.lex('aaabbbCCC') }
|
182
|
+
assert_raises(RLTK::LexingError) { ABLongest.lex('aaabbbCCC') }
|
193
183
|
end
|
194
184
|
|
195
185
|
def test_longest_match
|
196
|
-
expected =
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
]
|
186
|
+
expected = [
|
187
|
+
RLTK::Token.new(:APLUSBPLUS),
|
188
|
+
RLTK::Token.new(:EOS)
|
189
|
+
]
|
201
190
|
|
202
191
|
actual = ABLongest.lex('aaabbb')
|
203
192
|
|
@@ -205,19 +194,18 @@ class LexerTester < Test::Unit::TestCase
|
|
205
194
|
end
|
206
195
|
|
207
196
|
def test_match_data
|
208
|
-
expected
|
209
|
-
actual
|
197
|
+
expected = [RLTK::Token.new(:FOO, ['', 'ccc']), RLTK::Token.new(:EOS)]
|
198
|
+
actual = MatchDataLexer.lex('accc')
|
210
199
|
|
211
200
|
assert_equal(expected, actual)
|
212
201
|
end
|
213
202
|
|
214
203
|
def test_state
|
215
|
-
expected =
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
]
|
204
|
+
expected = [
|
205
|
+
RLTK::Token.new(:A),
|
206
|
+
RLTK::Token.new(:A),
|
207
|
+
RLTK::Token.new(:EOS)
|
208
|
+
]
|
221
209
|
|
222
210
|
actual = StateLexer.lex('a (* bbb *) a')
|
223
211
|
assert_equal(expected, actual)
|