babel_bridge 0.4.1 → 0.5.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.
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ describe "basic parsing" do
4
+ include TestParserGenerator
5
+
6
+ it "string literal should work" do
7
+ new_parser do
8
+ rule :foo, "foo"
9
+ end
10
+
11
+ test_parse "foo"
12
+ test_parse("foo").offset.should == 0
13
+ test_parse("foo").text.length.should == 3
14
+ end
15
+
16
+ it ".as option should work" do
17
+ new_parser do
18
+ rule :foo, match("foo").as(:boo)
19
+ end
20
+
21
+ test_parse "foo"
22
+ test_parse("foo").boo.text.should == "foo"
23
+ end
24
+
25
+ it "regexp should work" do
26
+ new_parser do
27
+ rule :foo, /[0-9]+/
28
+ end
29
+
30
+ %w{ 0 1 10 123 1001 }.each do |numstr|
31
+ test_parse numstr
32
+ end
33
+ end
34
+
35
+ # bb uses some regexp optimizations which could fail if not matched @ the first character of the source
36
+ it "regexp should work even when it isn't the first match" do
37
+ new_parser do
38
+ rule :foo, /[0-9]+/
39
+ rule :foo, "hi", /[0-9]+/
40
+ end
41
+
42
+ test_parse "123"
43
+ test_parse "hi123"
44
+ end
45
+
46
+ it "test optional" do
47
+ new_parser do
48
+ rule :foo, "foo", :bar?
49
+ rule :bar, "bar"
50
+ end
51
+
52
+ test_parse "foo"
53
+ test_parse "foobar"
54
+ end
55
+
56
+ it "test could" do
57
+ new_parser do
58
+ rule :foo, could.match(/[a-z]/), /[a-zA-Z]+/
59
+ end
60
+ test_parse "FOO", :should_fail_at => 0
61
+ test_parse "fOO"
62
+ test_parse "foo"
63
+ end
64
+
65
+ it "test optional in the middle" do
66
+ new_parser do
67
+ rule :foo, "foo", match?("bar"), "foo"
68
+ end
69
+
70
+ test_parse "foofoo"
71
+ test_parse "foobarfoo"
72
+ end
73
+
74
+ # this seems a little strange, but it is correct behavior for a Parsing-Expression-Grammar parser
75
+ it "test_greedy_optional_middle" do
76
+ new_parser do
77
+ rule :foo, "foo", match?("foo"), "foo"
78
+ end
79
+
80
+ test_parse "foofoo", :should_fail_at => 6
81
+ test_parse "foofoofoo"
82
+ end
83
+
84
+ it "! (not-match) should work" do
85
+ new_parser do
86
+ rule :foo, match!("boo"), /[a-zA-Z]+/
87
+ end
88
+
89
+ test_parse "boo", :should_fail_at => 0
90
+ test_parse "foo"
91
+ test_parse "boO"
92
+ end
93
+
94
+ end
@@ -1,44 +1,7 @@
1
- require File.join(File.dirname(__FILE__),"..","lib","babel_bridge")
1
+ require 'spec_helper'
2
2
 
3
3
  describe BabelBridge do
4
- attr_accessor :parser
5
-
6
- def new_parser(&block)
7
- $parser_counter||=0
8
- $parser_counter+=1
9
- Object.const_set(klass_name="TestParser#{$parser_counter}",Class.new(BabelBridge::Parser,&block))
10
- @parser=Object.const_get(klass_name).new
11
- end
12
-
13
- #options
14
- # :parser
15
- # :failure_ok
16
- def test_parse(string,options={},&block)
17
- parser = options[:parser] || @parser
18
- res = parser.parse(string)
19
- yield res if res && block
20
- if options[:should_fail_at]
21
- res.should == nil
22
- parser.failure_index.should == options[:should_fail_at]
23
- elsif !options[:failure_ok]
24
- puts parser.parser_failure_info :verbose => true unless res
25
- res.should_not == nil
26
- end
27
- res
28
- end
29
-
30
- it "ignore_whitespace should work" do
31
- new_parser do
32
- ignore_whitespace
33
- rule :foobar, "foo", "bar"
34
- end
35
-
36
- test_parse "foobar"
37
- test_parse "foo bar"
38
- test_parse "foo \t \r \f \n bar"
39
- test_parse " foobar"
40
- test_parse "foobar "
41
- end
4
+ include TestParserGenerator
42
5
 
43
6
  it "the failure_index should be the furthest point reached, even if we managed to successfully match less" do
44
7
  new_parser do
@@ -65,71 +28,6 @@ describe BabelBridge do
65
28
  parser.parser_failure_info[partial_match_string].should == nil
66
29
  end
67
30
 
68
- it "include_whitespace should work" do
69
- new_parser do
70
- ignore_whitespace
71
-
72
- rule :pair, :statement, :end_statement, :statement
73
- rule :end_statement, rewind_whitespace, /([\t ]*[\n;])+/
74
- rule :statement, "0"
75
- end
76
-
77
- test_parse "0;0"
78
- test_parse "0\n0"
79
- test_parse "0 ; 0"
80
- test_parse "0 ; ; 0"
81
- test_parse "0 \n 0"
82
- test_parse "0 \n \n 0"
83
- test_parse "0 \n ; \n 0"
84
- test_parse "0 ; \n ;0"
85
- test_parse "0 0", :should_fail_at => 1
86
- end
87
-
88
- it "include_whitespace should work even with EmptyNodes" do
89
- new_parser do
90
- ignore_whitespace
91
-
92
- rule :pair, :statement, :end_statement, :statement
93
- rule :end_statement, rewind_whitespace, /([\t ]*[\n;])+/
94
- rule :statement, "0", :one?, :one?, :one?
95
- rule :one, "1"
96
- end
97
-
98
- test_parse "0;0"
99
- test_parse "01;0"
100
- test_parse "0\n0"
101
- test_parse "01\n0"
102
- test_parse "011\n0"
103
- test_parse "0111\n0"
104
- end
105
-
106
- it "include_whitespace should work with many" do
107
- new_parser do
108
- ignore_whitespace
109
- rule :statements, many(:statement,:end_statement)
110
- rule :end_statement, rewind_whitespace, /([\t ]*[;\n])+/
111
- rule :statement, "0"
112
- end
113
-
114
- test_parse "0"
115
- test_parse "0\n0"
116
- end
117
-
118
- it "custom ignore_whitespace should work" do
119
- new_parser do
120
- ignore_whitespace /[_\s]*/
121
-
122
- rule :foobar, "foo", "bar"
123
- end
124
-
125
- test_parse "foobar"
126
- test_parse "foo_bar"
127
- test_parse "foo_ bar"
128
- test_parse "foo _ bar"
129
- test_parse "foo bar"
130
- test_parse "foo-bar", :should_fail_at => 3
131
- end
132
-
133
31
  it "should work to have many-many parsing" do
134
32
  new_parser do
135
33
  rule :top, many(:bottom,";")
@@ -144,68 +42,14 @@ describe BabelBridge do
144
42
  test_parse "0,0,0;0;0,0,0"
145
43
  end
146
44
 
147
- it "should work to have many parsing with whitespace tricks" do
45
+ it "if a name can be optionally matched more than one time, it should always be an array of matchs" do
148
46
  new_parser do
149
- ignore_whitespace
150
- rule :statements, many(:statement,:end_statement)
151
- rule :end_statement, rewind_whitespace, /([\t ]*[;\n])+/
152
- rule :statement, :bin_op
153
- binary_operators_rule :bin_op, :int, ["**", [:/, :*], [:+, "-"]], :right_operators => ["**"]
154
- rule :int, /\d+/
155
- end
156
-
157
- test_parse "0"
158
- test_parse <<ENDCODE
159
- 3+4
160
- 9-2
161
- 4
162
- ENDCODE
163
- end
164
-
165
- it "should work to rewind_whitespace, :rule" do
166
- new_parser do
167
- ignore_whitespace
168
- rule :all, :identifier, :parameter?, :identifier do
169
- def to_model
170
- [[identifier[0].to_sym, parameter && parameter.to_sym], identifier[1].to_sym]
171
- end
172
- end
173
- rule :parameter, rewind_whitespace, /[ \t]*/, rewind_whitespace, :identifier
174
- rule :identifier, /[_a-zA-Z][_a-zA-Z0-9]*/
175
- end
176
-
177
- test_parse("fred\nbar") {|parsed|parsed.to_model.should == [[:fred,nil],:bar]}
178
- test_parse("fred foo\nbar") {|parsed|parsed.to_model.should == [[:fred,:foo],:bar]}
179
- end
180
-
181
- it "should work to rewind_whitespace, many" do
182
- new_parser do
183
- ignore_whitespace
184
- rule :all, :identifier, :parameters?, :identifier do
185
- def to_model
186
- [[identifier[0].to_sym, parameters && parameters.to_s], identifier[1].to_sym]
187
- end
188
- end
189
- rule :parameters, rewind_whitespace, /[ \t]*/, rewind_whitespace, many(:identifier,",")
190
- rule :identifier, /[_a-zA-Z][_a-zA-Z0-9]*/
191
- end
192
-
193
- test_parse("fred\nbar") {|parsed| parsed.to_model.should==[[:fred,nil],:bar]}
194
- test_parse("fred foo\nbar") {|parsed| parsed.to_model.should==[[:fred,"foo"],:bar]}
195
- test_parse("fred foo, bar\nbar") {|parsed| parsed.to_model.should==[[:fred,"foo, bar"],:bar]}
196
- end
197
-
198
- it "dont.match shouldn't consume any whitespace" do
199
- new_parser do
200
- ignore_whitespace
201
- rule :statements, :statement, "bar"
202
- rule :statement, :identifier, :parameters?
203
- rule :parameters, rewind_whitespace, / */, rewind_whitespace, :identifier
204
- rule :identifier, dont.match("end"), /[_a-zA-Z][_a-zA-Z0-9]*/
47
+ rule :foo, :bar, :bar?
48
+ rule :bar, "bar"
205
49
  end
206
50
 
207
- test_parse("fred\nbar")
208
- test_parse("fred foo\nbar")
51
+ test_parse("bar").bar.class.should == BabelBridge::MultiMatchesArray
52
+ test_parse("barbar").bar.class.should == BabelBridge::MultiMatchesArray
209
53
  end
210
54
 
211
55
  end
@@ -0,0 +1,227 @@
1
+ require 'spec_helper'
2
+
3
+ describe "ignore_whitespace" do
4
+ include TestParserGenerator
5
+
6
+ it "ignore_whitespace should work" do
7
+ new_parser do
8
+ ignore_whitespace
9
+ rule :foobar, "foo", "bar"
10
+ end
11
+
12
+ # test_parse "foobar"
13
+ # test_parse "foo bar"
14
+ # test_parse "foo \t \r \f \n bar"
15
+ # test_parse " foobar"
16
+ test_parse "foobar "
17
+ end
18
+
19
+ it "ignore_whitespace should work with many" do
20
+ new_parser do
21
+ ignore_whitespace
22
+ rule :foobar, many("foo")
23
+ end
24
+
25
+ test_parse "foo"
26
+ test_parse "foofoo"
27
+ test_parse "foo foo"
28
+ test_parse "foo foo\nfoo"
29
+ end
30
+
31
+ it "custom delimiter should work" do
32
+ new_parser do
33
+ ignore_whitespace
34
+ rule :pair, "0", "0", :delimiter => /-*/
35
+ end
36
+
37
+ test_parse "00"
38
+ test_parse "0-0"
39
+ test_parse " 0-0"
40
+ test_parse " 0-0 "
41
+ test_parse " 0--0 "
42
+ end
43
+
44
+ it "custom // delimiter should work" do
45
+ new_parser do
46
+ ignore_whitespace
47
+ rule :pair, "0", "0", :delimiter => //
48
+ end
49
+
50
+ test_parse "00"
51
+ test_parse " 00"
52
+ test_parse " 00 "
53
+ test_parse "0 0", :should_fail_at => 1
54
+ end
55
+
56
+
57
+ it "custom delimiter should work" do
58
+ new_parser do
59
+ ignore_whitespace
60
+
61
+ rule :pair, :statement, :end_statement, :statement, :delimiter => //
62
+ rule :end_statement, /([\t ]*[\n;])+([\t ]*)?/
63
+ rule :statement, "0"
64
+ end
65
+
66
+ test_parse "0;0"
67
+ test_parse "0\n0"
68
+ test_parse "0 ; 0"
69
+ test_parse "0 ; ; 0"
70
+ test_parse "0 \n 0"
71
+ test_parse "0 \n \n 0"
72
+ test_parse "0 \n ; \n 0"
73
+ test_parse "0 ; \n ;0"
74
+ test_parse "0 0", :should_fail_at => 1
75
+ end
76
+
77
+ it "custom delimiters should work even with EmptyNodes" do
78
+ new_parser do
79
+ ignore_whitespace
80
+
81
+ rule :pair, :statement, :end_statement, :statement, :delimiter => //
82
+ rule :end_statement, /([\t ]*[\n;])+([\t ]*)?/
83
+ rule :statement, "0", :one?, :one?, :one?
84
+ rule :one, "1"
85
+ end
86
+
87
+ test_parse "0;0"
88
+ test_parse "01;0"
89
+ test_parse "0\n0"
90
+ test_parse "01\n0"
91
+ test_parse "011\n0"
92
+ test_parse "0111\n0"
93
+ end
94
+
95
+ it "custom delimiters should work with many" do
96
+ new_parser do
97
+ ignore_whitespace
98
+ rule :statements, many(:statement,:end_statement), :delimiter => //
99
+ rule :end_statement, /([\t ]*[\n;])+([\t ]*)?/
100
+ rule :statement, "0"
101
+ end
102
+
103
+ test_parse "0"
104
+ test_parse "0\n0"
105
+ test_parse "0\n0;0"
106
+ test_parse "0 0", :should_fail_at => 2
107
+ end
108
+
109
+ it "custom global delimiter should work" do
110
+ new_parser do
111
+ delimiter /[_\s]*/
112
+
113
+ rule :foobar, "foo", "bar"
114
+ end
115
+
116
+ test_parse "foobar"
117
+ test_parse "foo_bar"
118
+ test_parse "foo_ bar"
119
+ test_parse "foo _ bar"
120
+ test_parse "foo bar"
121
+ test_parse "foo-bar", :should_fail_at => 3
122
+ end
123
+
124
+
125
+ it "should work to rewind_whitespace, :rule" do
126
+ new_parser do
127
+ ignore_whitespace
128
+ rule :two, :statement, :statement do
129
+ def to_model
130
+ statement.map {|a|a.to_model}
131
+ end
132
+ end
133
+ rule :statement, :identifier, :parameter?, :delimiter => // do
134
+ def to_model
135
+ [identifier.to_sym, parameter && parameter.identifier.to_sym]
136
+ end
137
+ end
138
+ rule :parameter, /[ \t]*/, :identifier, :delimiter => //
139
+ rule :identifier, /[_a-zA-Z][_a-zA-Z0-9]*/
140
+ end
141
+
142
+ test_parse("fred\nbar") {|parsed|parsed.to_model.should == [[:fred,nil],[:bar,nil]]}
143
+ test_parse("fred foo\nbar") {|parsed|parsed.to_model.should == [[:fred,:foo],[:bar,nil]]}
144
+ end
145
+
146
+ it "should work to have nested custom delimiters" do
147
+ new_parser do
148
+ ignore_whitespace
149
+ rule :all, :call, :call do
150
+ def to_model
151
+ call.collect &:to_model
152
+ end
153
+ end
154
+ rule :call, :identifier, :parameters?, :delimiter => // do
155
+ def to_model
156
+ [identifier.to_sym, parameters && parameters.to_s]
157
+ end
158
+ end
159
+ rule :parameters, /[ \t]*/, many(:identifier,","), :delimiter => //
160
+ rule :identifier, /[_a-zA-Z][_a-zA-Z0-9]*/
161
+ end
162
+
163
+ test_parse("fred\nbar") {|parsed| parsed.to_model.should==[[:fred,nil],[:bar,nil]]}
164
+ test_parse("fred foo\nbar") {|parsed| parsed.to_model.should==[[:fred," foo"],[:bar,nil]]}
165
+ test_parse("fred foo,bar\nbar") {|parsed| parsed.to_model.should==[[:fred," foo,bar"],[:bar,nil]]}
166
+ end
167
+
168
+ it "dont.match shouldn't consume any whitespace" do
169
+ new_parser do
170
+ ignore_whitespace
171
+ rule :statements, :statement, "bar"
172
+ rule :statement, :identifier, :parameters?, :delimiter => //
173
+ rule :parameters, / */, :identifier, :delimiter => //
174
+ rule :identifier, dont.match("end"), /[_a-zA-Z][_a-zA-Z0-9]*/
175
+ end
176
+
177
+ test_parse("fred\nbar")
178
+ #test_parse("fred foo\nbar")
179
+ end
180
+
181
+ it "delimiter should work" do
182
+ new_parser do
183
+ delimiter :custom_delimiter
184
+ rule :foobar, "foo", "bar"
185
+ rule :custom_delimiter, /-*/
186
+ end
187
+
188
+ test_parse "foobar"
189
+ test_parse "foo-bar"
190
+ test_parse "foo---bar"
191
+ end
192
+
193
+ it "should work to have many parsing with whitespace tricks" do
194
+ new_parser do
195
+ ignore_whitespace
196
+ #rule :statements, many(:statement,:end_statement), :delimiter => //
197
+ #rule :end_statement, /([\t ]*[;\n])+/
198
+ #rule :statement, :bin_op
199
+ binary_operators_rule :bin_op, :int, ["**", [:/, :*], [:+, "-"]], :right_operators => ["**"]
200
+ rule :int, /\d+/
201
+ end
202
+
203
+ =begin
204
+ NOTES: the problem is the post-parsing results method-missing methods don't work well.
205
+
206
+ If a named pattern is never matched, method-missing will fail. It should return nil.
207
+ If a named pattern may match 1 or more times, you will get back a singleton OR an array depending on the number of times.
208
+
209
+ I think the right answer is to drop method-missing entirely. Instead, when the rule is declared, create the accessor methods explicitly.
210
+
211
+ If a named pattern could match more than once, it will always return an array.
212
+
213
+ If it could match 0 times, it will work and return nil, if 0 times were indeed matched.
214
+
215
+ =end
216
+ test_parse "3"
217
+ =begin
218
+ test_parse "3+4"
219
+ test_parse <<ENDCODE
220
+ 3+4
221
+ 9-2
222
+ 4
223
+ ENDCODE
224
+ =end
225
+ end
226
+
227
+ end