rltk 2.2.1 → 3.0.0
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/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)
|