Spectre 0.0.1
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.
- data/CHANGELOG +1 -0
- data/LICENSE +23 -0
- data/README +20 -0
- data/Rakefile +112 -0
- data/lib/spectre/base.rb +44 -0
- data/lib/spectre/base/closure.rb +96 -0
- data/lib/spectre/base/directive.rb +148 -0
- data/lib/spectre/base/grammar.rb +269 -0
- data/lib/spectre/base/inputiterator.rb +276 -0
- data/lib/spectre/base/node.rb +393 -0
- data/lib/spectre/base/operators.rb +342 -0
- data/lib/spectre/base/parser.rb +110 -0
- data/lib/spectre/generic.rb +115 -0
- data/lib/spectre/generic/directives.rb +246 -0
- data/lib/spectre/generic/negations.rb +68 -0
- data/lib/spectre/generic/primitives.rb +172 -0
- data/lib/spectre/generic/semanticaction.rb +43 -0
- data/lib/spectre/string.rb +57 -0
- data/lib/spectre/string/additionals.rb +80 -0
- data/lib/spectre/string/directives.rb +51 -0
- data/lib/spectre/string/inputiterator.rb +57 -0
- data/lib/spectre/string/primitives.rb +400 -0
- data/test/base/closure_tests.rb +108 -0
- data/test/base/grammar_tests.rb +97 -0
- data/test/base/operator_tests.rb +335 -0
- data/test/base/semanticaction_tests.rb +53 -0
- data/test/generic/directive_tests.rb +224 -0
- data/test/generic/negation_tests.rb +146 -0
- data/test/generic/primitive_tests.rb +99 -0
- data/test/string/POD2Parser_tests.rb +93 -0
- data/test/string/additional_tests.rb +43 -0
- data/test/string/directive_tests.rb +32 -0
- data/test/string/primitive_tests.rb +173 -0
- data/test/tests.rb +33 -0
- data/test/tutorial/funnymath_tests.rb +57 -0
- data/test/tutorial/html_tests.rb +171 -0
- data/test/tutorial/skipping_tests.rb +60 -0
- metadata +109 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This is Spectre, a parser framework inspired by Boost.Spirit,
|
3
|
+
# which can be found at http://spirit.sourceforge.net/.
|
4
|
+
#
|
5
|
+
# If you want to find out more or need a tutorial, go to
|
6
|
+
# http://spectre.rubyforge.org/
|
7
|
+
# You'll find a nice wiki there!
|
8
|
+
#
|
9
|
+
# Author:: Fabian Streitel (karottenreibe)
|
10
|
+
# Copyright:: Copyright (c) 2009 Fabian Streitel
|
11
|
+
# License:: Boost Software License 1.0
|
12
|
+
# For further information regarding this license, you can go to
|
13
|
+
# http://www.boost.org/LICENSE_1_0.txt
|
14
|
+
# or read the file LICENSE distributed with this software.
|
15
|
+
# Homepage:: http://spectre.rubyforge.org/
|
16
|
+
# Git repo:: http://rubyforge.org/scm/?group_id=7618
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'test/unit'
|
21
|
+
require 'spectre/string'
|
22
|
+
|
23
|
+
class ClosureTests < Test::Unit::TestCase
|
24
|
+
include Spectre
|
25
|
+
include Spectre::StringParsing
|
26
|
+
include Spectre::ShortcutsMixin
|
27
|
+
|
28
|
+
def testClosureFinding
|
29
|
+
p3 = 'bacon'.to_p
|
30
|
+
p2 = ' ' >> p3
|
31
|
+
p = 'chunky' >> p2
|
32
|
+
|
33
|
+
c = p.closure = Closure.new
|
34
|
+
assert_same c, p.closure
|
35
|
+
assert_same c, p2.closure
|
36
|
+
assert_same c, p3.closure
|
37
|
+
end
|
38
|
+
|
39
|
+
def testClosureFindingGram
|
40
|
+
g = Grammar.new do
|
41
|
+
start_with 'bar'.to_p[:tag]
|
42
|
+
end
|
43
|
+
|
44
|
+
g.bind
|
45
|
+
|
46
|
+
c = g.closure = Closure.new
|
47
|
+
parse 'bar', g
|
48
|
+
assert_equal 'bar', c[:tag]
|
49
|
+
|
50
|
+
g = Grammar.new do
|
51
|
+
start_with close( 'bar'.to_p[:tag] )
|
52
|
+
end
|
53
|
+
|
54
|
+
c = g.closure = Closure.new
|
55
|
+
g.bind
|
56
|
+
|
57
|
+
parse 'bar', g
|
58
|
+
assert_equal nil, c[:tag]
|
59
|
+
end
|
60
|
+
|
61
|
+
def testClosureHierarchy
|
62
|
+
p1 = 'chunky' >> blank_char >> 'bacon'
|
63
|
+
p11 = p1.dup
|
64
|
+
p2 = p1 >> blank_char >> p11
|
65
|
+
|
66
|
+
c1 = Closure.new
|
67
|
+
c2 = Closure.new
|
68
|
+
p1.closure = c1
|
69
|
+
p2.closure = c2
|
70
|
+
|
71
|
+
assert_same c2, p2.closure
|
72
|
+
assert_same c2, p11.closure
|
73
|
+
assert_same c1, p1.closure
|
74
|
+
assert_not_same c2, p1.closure
|
75
|
+
assert_same c2, p1.parent.closure
|
76
|
+
end
|
77
|
+
|
78
|
+
def testGrammarClosure
|
79
|
+
val = 0
|
80
|
+
tester = lambda { |match,closure| assert_kind_of Closure, closure }
|
81
|
+
|
82
|
+
g = Grammar.new do
|
83
|
+
rule :expr => close( :term.to_p[tester] | :plus | :minus )[tester]
|
84
|
+
rule :term => alnum_char
|
85
|
+
rule :plus => '('.to_p >> :expr >> '+' >> :expr >> ')'
|
86
|
+
rule :minus => '(' >> :expr.to_p[tester] >> '-' >> :expr >> ')'
|
87
|
+
start_with :expr.to_p
|
88
|
+
end.bind
|
89
|
+
|
90
|
+
parse '((a-b)+c)', g
|
91
|
+
end
|
92
|
+
|
93
|
+
def testGrammarParents
|
94
|
+
val = 0
|
95
|
+
tester = lambda { |match,closure| p closure[:term]; p match }
|
96
|
+
|
97
|
+
g = Grammar.new do
|
98
|
+
rule :expr => close( :term.to_p | :plus | :minus )
|
99
|
+
rule :term => close( alnum_char[:term] )
|
100
|
+
rule :plus => '('.to_p >> :expr >> '+' >> :expr >> ')'
|
101
|
+
rule :minus => '('.to_p >> :expr >> '-' >> :expr >> ')'
|
102
|
+
start_with :expr.to_p
|
103
|
+
end.bind
|
104
|
+
|
105
|
+
parse '((a-b)+c)', g
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This is Spectre, a parser framework inspired by Boost.Spirit,
|
3
|
+
# which can be found at http://spirit.sourceforge.net/.
|
4
|
+
#
|
5
|
+
# If you want to find out more or need a tutorial, go to
|
6
|
+
# http://spectre.rubyforge.org/
|
7
|
+
# You'll find a nice wiki there!
|
8
|
+
#
|
9
|
+
# Author:: Fabian Streitel (karottenreibe)
|
10
|
+
# Copyright:: Copyright (c) 2009 Fabian Streitel
|
11
|
+
# License:: Boost Software License 1.0
|
12
|
+
# For further information regarding this license, you can go to
|
13
|
+
# http://www.boost.org/LICENSE_1_0.txt
|
14
|
+
# or read the file LICENSE distributed with this software.
|
15
|
+
# Homepage:: http://spectre.rubyforge.org/
|
16
|
+
# Git repo:: http://rubyforge.org/scm/?group_id=7618
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'test/unit'
|
21
|
+
require 'spectre/string'
|
22
|
+
|
23
|
+
class GrammarTests < Test::Unit::TestCase
|
24
|
+
include Spectre
|
25
|
+
include Spectre::StringParsing
|
26
|
+
|
27
|
+
def testSimpleGrammar
|
28
|
+
simple_grammar = Grammar.new do ||
|
29
|
+
rule :rule => alnum_char % ','
|
30
|
+
start_with :rule
|
31
|
+
end
|
32
|
+
|
33
|
+
ret = parse "a,b,c,1,2,3", simple_grammar
|
34
|
+
assert_equal 11, ret.length
|
35
|
+
assert_equal "a,b,c,1,2,3", ret.value
|
36
|
+
end
|
37
|
+
|
38
|
+
def testHTMLGrammar
|
39
|
+
html_grammar = Grammar.new do ||
|
40
|
+
rule :tag => '<'.to_p >> :tagname >> '>'
|
41
|
+
rule :endtag => '</'.to_p >> :tagname >> '>'
|
42
|
+
rule :tagname => ( ~char('>') ).+
|
43
|
+
rule :data => lexeme_d[( ~char('<') ).+]
|
44
|
+
rule :inner => :data.to_p | :element
|
45
|
+
rule :element => :tag.to_p >> :inner >> :endtag
|
46
|
+
start_with :element
|
47
|
+
end
|
48
|
+
|
49
|
+
html = "<html><body><p>print me!</p></body></html>"
|
50
|
+
ret = parse html, html_grammar
|
51
|
+
assert_kind_of Match, ret
|
52
|
+
assert_equal html.length, ret.length
|
53
|
+
assert_equal html, ret.value
|
54
|
+
end
|
55
|
+
|
56
|
+
def testGrammarArgs
|
57
|
+
dyn = Grammar.new do |op1, op2|
|
58
|
+
rule :expr => :term.to_p | :o1 | :o2,
|
59
|
+
:term => alnum_char.+,
|
60
|
+
:o1 => '('.to_p >> :expr >> op1.to_p >> :expr >> ')',
|
61
|
+
:o2 => '('.to_p >> :expr >> op2.to_p >> :expr >> ')'
|
62
|
+
start_with :expr
|
63
|
+
end
|
64
|
+
|
65
|
+
dyn.bind('+', '-')
|
66
|
+
ex = '(A+(3-B))'
|
67
|
+
ret = parse ex, dyn
|
68
|
+
assert_kind_of Match, ret
|
69
|
+
assert_equal ex.length, ret.length
|
70
|
+
assert_equal ex, ret.value
|
71
|
+
|
72
|
+
dyn.bind('*', '/')
|
73
|
+
ex = '(A*(22*((33*B)/44)))'
|
74
|
+
ret = parse ex, dyn
|
75
|
+
assert_kind_of Match, ret
|
76
|
+
assert_equal ex.length, ret.length
|
77
|
+
assert_equal ex, ret.value
|
78
|
+
end
|
79
|
+
|
80
|
+
class MixinTester
|
81
|
+
include Spectre::ShortcutsMixin
|
82
|
+
end
|
83
|
+
|
84
|
+
class FooParser
|
85
|
+
include Spectre::Parser
|
86
|
+
end
|
87
|
+
|
88
|
+
def testShortcutsMixin
|
89
|
+
before = MixinTester.new
|
90
|
+
ShortcutsMixin.register_shortcut :foo => FooParser
|
91
|
+
after = MixinTester.new
|
92
|
+
|
93
|
+
assert_respond_to after, :foo
|
94
|
+
assert_respond_to before, :foo
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
@@ -0,0 +1,335 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This is Spectre, a parser framework inspired by Boost.Spirit,
|
3
|
+
# which can be found at http://spirit.sourceforge.net/.
|
4
|
+
#
|
5
|
+
# If you want to find out more or need a tutorial, go to
|
6
|
+
# http://spectre.rubyforge.org/
|
7
|
+
# You'll find a nice wiki there!
|
8
|
+
#
|
9
|
+
# Author:: Fabian Streitel (karottenreibe)
|
10
|
+
# Copyright:: Copyright (c) 2009 Fabian Streitel
|
11
|
+
# License:: Boost Software License 1.0
|
12
|
+
# For further information regarding this license, you can go to
|
13
|
+
# http://www.boost.org/LICENSE_1_0.txt
|
14
|
+
# or read the file LICENSE distributed with this software.
|
15
|
+
# Homepage:: http://spectre.rubyforge.org/
|
16
|
+
# Git repo:: http://rubyforge.org/scm/?group_id=7618
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'test/unit'
|
21
|
+
require 'spectre/string'
|
22
|
+
|
23
|
+
class StringOperatorTests < Test::Unit::TestCase
|
24
|
+
include Spectre
|
25
|
+
include Spectre::Operators
|
26
|
+
include Spectre::StringParsing
|
27
|
+
|
28
|
+
def testSequence
|
29
|
+
p = Node.new Sequence.new, CharParser.new("a"), CharParser.new("s")
|
30
|
+
iter = StringInputIterator.new "asdf"
|
31
|
+
ret = p.parse iter
|
32
|
+
assert_kind_of Match, ret
|
33
|
+
assert_equal 2, ret.length
|
34
|
+
assert_equal "as", ret.value
|
35
|
+
assert_equal 2, iter.pos
|
36
|
+
|
37
|
+
iter = StringInputIterator.new "a sdf"
|
38
|
+
ret = p.parse iter
|
39
|
+
assert_kind_of Match, ret
|
40
|
+
assert_equal 3, ret.length
|
41
|
+
assert_equal "as", ret.value
|
42
|
+
assert_equal 3, iter.pos
|
43
|
+
|
44
|
+
iter = StringInputIterator.new "bsdf"
|
45
|
+
ret = p.parse iter
|
46
|
+
assert_kind_of NilClass, ret
|
47
|
+
assert_equal 0, iter.pos
|
48
|
+
|
49
|
+
iter = StringInputIterator.new "abdf"
|
50
|
+
ret = p.parse iter
|
51
|
+
assert_kind_of NilClass, ret
|
52
|
+
assert_equal 0, iter.pos
|
53
|
+
end
|
54
|
+
|
55
|
+
def testSequentialOr
|
56
|
+
p = Node.new SequentialOr.new, CharParser.new("a"), CharParser.new("s")
|
57
|
+
|
58
|
+
iter = StringInputIterator.new "asdf"
|
59
|
+
ret = p.parse iter
|
60
|
+
assert_kind_of Match, ret
|
61
|
+
assert_equal 2, ret.length
|
62
|
+
assert_equal "as", ret.value
|
63
|
+
assert_equal 2, iter.pos
|
64
|
+
|
65
|
+
iter = StringInputIterator.new "a s df"
|
66
|
+
ret = p.parse iter
|
67
|
+
assert_kind_of Match, ret
|
68
|
+
assert_equal 3, ret.length
|
69
|
+
assert_equal "as", ret.value
|
70
|
+
assert_equal 3, iter.pos
|
71
|
+
|
72
|
+
iter = StringInputIterator.new "a3df"
|
73
|
+
ret = p.parse iter
|
74
|
+
assert_kind_of Match, ret
|
75
|
+
assert_equal 1, ret.length
|
76
|
+
assert_equal "a", ret.value
|
77
|
+
assert_equal 1, iter.pos
|
78
|
+
|
79
|
+
iter = StringInputIterator.new "bsdf"
|
80
|
+
ret = p.parse iter
|
81
|
+
assert_kind_of NilClass, ret
|
82
|
+
assert_equal 0, iter.pos
|
83
|
+
end
|
84
|
+
|
85
|
+
def testUnion
|
86
|
+
p = Node.new Union.new, CharParser.new("a"), CharParser.new("s")
|
87
|
+
iter = StringInputIterator.new "asdf"
|
88
|
+
ret = p.parse iter
|
89
|
+
assert_kind_of Match, ret
|
90
|
+
assert_equal 1, ret.length
|
91
|
+
assert_equal "a", ret.value
|
92
|
+
assert_equal 1, iter.pos
|
93
|
+
|
94
|
+
iter = StringInputIterator.new "s3df"
|
95
|
+
ret = p.parse iter
|
96
|
+
assert_kind_of Match, ret
|
97
|
+
assert_equal 1, ret.length
|
98
|
+
assert_equal "s", ret.value
|
99
|
+
assert_equal 1, iter.pos
|
100
|
+
|
101
|
+
iter = StringInputIterator.new " s 3df"
|
102
|
+
ret = p.parse iter
|
103
|
+
assert_kind_of Match, ret
|
104
|
+
assert_equal 3, ret.length
|
105
|
+
assert_equal "s", ret.value
|
106
|
+
assert_equal 3, iter.pos
|
107
|
+
|
108
|
+
iter = StringInputIterator.new "bsdf"
|
109
|
+
ret = p.parse iter
|
110
|
+
assert_kind_of NilClass, ret
|
111
|
+
assert_equal 0, iter.pos
|
112
|
+
end
|
113
|
+
|
114
|
+
def testIntersection
|
115
|
+
p = Node.new Intersection.new, RangeParser.new("a".."b"), RangeParser.new("a".."c")
|
116
|
+
iter = StringInputIterator.new "asdf"
|
117
|
+
ret = p.parse iter
|
118
|
+
assert_kind_of Match, ret
|
119
|
+
assert_equal 1, ret.length
|
120
|
+
assert_equal "a", ret.value
|
121
|
+
assert_equal 1, iter.pos
|
122
|
+
|
123
|
+
iter = StringInputIterator.new "b3df"
|
124
|
+
ret = p.parse iter
|
125
|
+
assert_kind_of Match, ret
|
126
|
+
assert_equal 1, ret.length
|
127
|
+
assert_equal "b", ret.value
|
128
|
+
assert_equal 1, iter.pos
|
129
|
+
|
130
|
+
iter = StringInputIterator.new " b3df"
|
131
|
+
ret = p.parse iter
|
132
|
+
assert_kind_of Match, ret
|
133
|
+
assert_equal 3, ret.length
|
134
|
+
assert_equal "b", ret.value
|
135
|
+
assert_equal 3, iter.pos
|
136
|
+
|
137
|
+
iter = StringInputIterator.new "csdf"
|
138
|
+
ret = p.parse iter
|
139
|
+
assert_kind_of NilClass, ret
|
140
|
+
assert_equal 0, iter.pos
|
141
|
+
|
142
|
+
iter = StringInputIterator.new "xsdf"
|
143
|
+
ret = p.parse iter
|
144
|
+
assert_kind_of NilClass, ret
|
145
|
+
assert_equal 0, iter.pos
|
146
|
+
end
|
147
|
+
|
148
|
+
def testDifference
|
149
|
+
p = Node.new Difference.new, RangeParser.new("a".."c"), RangeParser.new("a".."b")
|
150
|
+
iter = StringInputIterator.new "csdf"
|
151
|
+
ret = p.parse iter
|
152
|
+
assert_kind_of Match, ret
|
153
|
+
assert_equal 1, ret.length
|
154
|
+
assert_equal "c", ret.value
|
155
|
+
assert_equal 1, iter.pos
|
156
|
+
|
157
|
+
iter = StringInputIterator.new " csdf"
|
158
|
+
ret = p.parse iter
|
159
|
+
assert_kind_of Match, ret
|
160
|
+
assert_equal 2, ret.length
|
161
|
+
assert_equal "c", ret.value
|
162
|
+
assert_equal 2, iter.pos
|
163
|
+
|
164
|
+
iter = StringInputIterator.new "a3df"
|
165
|
+
ret = p.parse iter
|
166
|
+
assert_kind_of NilClass, ret
|
167
|
+
assert_equal 0, iter.pos
|
168
|
+
|
169
|
+
iter = StringInputIterator.new "xsdf"
|
170
|
+
ret = p.parse iter
|
171
|
+
assert_kind_of NilClass, ret
|
172
|
+
assert_equal 0, iter.pos
|
173
|
+
end
|
174
|
+
|
175
|
+
def testXor
|
176
|
+
p = Node.new Xor.new, RangeParser.new("b".."x"), RangeParser.new("a".."b")
|
177
|
+
iter = StringInputIterator.new "asdf"
|
178
|
+
ret = p.parse iter
|
179
|
+
assert_kind_of Match, ret
|
180
|
+
assert_equal 1, ret.length
|
181
|
+
assert_equal "a", ret.value
|
182
|
+
assert_equal 1, iter.pos
|
183
|
+
|
184
|
+
iter = StringInputIterator.new " t3df"
|
185
|
+
ret = p.parse iter
|
186
|
+
assert_kind_of Match, ret
|
187
|
+
assert_equal 4, ret.length
|
188
|
+
assert_equal "t", ret.value
|
189
|
+
assert_equal 4, iter.pos
|
190
|
+
|
191
|
+
iter = StringInputIterator.new "t3df"
|
192
|
+
ret = p.parse iter
|
193
|
+
assert_kind_of Match, ret
|
194
|
+
assert_equal 1, ret.length
|
195
|
+
assert_equal "t", ret.value
|
196
|
+
assert_equal 1, iter.pos
|
197
|
+
|
198
|
+
iter = StringInputIterator.new "bsdf"
|
199
|
+
ret = p.parse iter
|
200
|
+
assert_kind_of NilClass, ret
|
201
|
+
assert_equal 0, iter.pos
|
202
|
+
|
203
|
+
iter = StringInputIterator.new "3sdf"
|
204
|
+
ret = p.parse iter
|
205
|
+
assert_kind_of NilClass, ret
|
206
|
+
assert_equal 0, iter.pos
|
207
|
+
end
|
208
|
+
|
209
|
+
def testKleeneStar
|
210
|
+
p = Node.new KleeneStar.new, RangeParser.new("a".."s")
|
211
|
+
iter = StringInputIterator.new "asdf"
|
212
|
+
ret = p.parse iter
|
213
|
+
assert_kind_of Match, ret
|
214
|
+
assert_equal 4, ret.length
|
215
|
+
assert_equal "asdf", ret.value
|
216
|
+
assert_equal 4, iter.pos
|
217
|
+
|
218
|
+
iter = StringInputIterator.new "a3df"
|
219
|
+
ret = p.parse iter
|
220
|
+
assert_kind_of Match, ret
|
221
|
+
assert_equal 1, ret.length
|
222
|
+
assert_equal "a", ret.value
|
223
|
+
assert_equal 1, iter.pos
|
224
|
+
|
225
|
+
iter = StringInputIterator.new " a3df"
|
226
|
+
ret = p.parse iter
|
227
|
+
assert_kind_of Match, ret
|
228
|
+
assert_equal 2, ret.length
|
229
|
+
assert_equal "a", ret.value
|
230
|
+
assert_equal 2, iter.pos
|
231
|
+
|
232
|
+
iter = StringInputIterator.new "3sdf"
|
233
|
+
ret = p.parse iter
|
234
|
+
assert_kind_of Match, ret
|
235
|
+
assert_equal 0, ret.length
|
236
|
+
assert_equal "", ret.value
|
237
|
+
assert_equal 0, iter.pos
|
238
|
+
end
|
239
|
+
|
240
|
+
def testPositive
|
241
|
+
p = Node.new Positive.new, CharParser.new("a")
|
242
|
+
iter = StringInputIterator.new "aaaa"
|
243
|
+
ret = p.parse iter
|
244
|
+
assert_kind_of Match, ret
|
245
|
+
assert_equal 4, ret.length
|
246
|
+
assert_equal "aaaa", ret.value
|
247
|
+
assert_equal 4, iter.pos
|
248
|
+
|
249
|
+
iter = StringInputIterator.new " a3df"
|
250
|
+
ret = p.parse iter
|
251
|
+
assert_kind_of Match, ret
|
252
|
+
assert_equal 2, ret.length
|
253
|
+
assert_equal "a", ret.value
|
254
|
+
assert_equal 2, iter.pos
|
255
|
+
|
256
|
+
iter = StringInputIterator.new "a3df"
|
257
|
+
ret = p.parse iter
|
258
|
+
assert_kind_of Match, ret
|
259
|
+
assert_equal 1, ret.length
|
260
|
+
assert_equal "a", ret.value
|
261
|
+
assert_equal 1, iter.pos
|
262
|
+
|
263
|
+
iter = StringInputIterator.new "3sdf"
|
264
|
+
ret = p.parse iter
|
265
|
+
assert_kind_of NilClass, ret
|
266
|
+
assert_equal 0, iter.pos
|
267
|
+
end
|
268
|
+
|
269
|
+
def testOptional
|
270
|
+
p = Node.new Optional.new, CharParser.new("a")
|
271
|
+
iter = StringInputIterator.new "asdf"
|
272
|
+
ret = p.parse iter
|
273
|
+
assert_kind_of Match, ret
|
274
|
+
assert_equal 1, ret.length
|
275
|
+
assert_equal "a", ret.value
|
276
|
+
assert_equal 1, iter.pos
|
277
|
+
|
278
|
+
iter = StringInputIterator.new "33df"
|
279
|
+
ret = p.parse iter
|
280
|
+
assert_kind_of Match, ret
|
281
|
+
assert_equal 0, ret.length
|
282
|
+
assert_equal "", ret.value
|
283
|
+
assert_equal 0, iter.pos
|
284
|
+
|
285
|
+
iter = StringInputIterator.new " a3df"
|
286
|
+
ret = p.parse iter
|
287
|
+
assert_kind_of Match, ret
|
288
|
+
assert_equal 3, ret.length
|
289
|
+
assert_equal "a", ret.value
|
290
|
+
assert_equal 3, iter.pos
|
291
|
+
end
|
292
|
+
|
293
|
+
def testList
|
294
|
+
p = Node.new List.new, CharParser.new("a"), CharParser.new("s")
|
295
|
+
iter = StringInputIterator.new "asasa"
|
296
|
+
ret = p.parse iter
|
297
|
+
assert_kind_of Match, ret
|
298
|
+
assert_equal 5, ret.length
|
299
|
+
assert_equal "asasa", ret.value
|
300
|
+
assert_equal 5, iter.pos
|
301
|
+
|
302
|
+
iter = StringInputIterator.new "asas"
|
303
|
+
ret = p.parse iter
|
304
|
+
assert_kind_of Match, ret
|
305
|
+
assert_equal 3, ret.length
|
306
|
+
assert_equal "asa", ret.value
|
307
|
+
assert_equal 3, iter.pos
|
308
|
+
|
309
|
+
iter = StringInputIterator.new "a s a s a"
|
310
|
+
ret = p.parse iter
|
311
|
+
assert_kind_of Match, ret
|
312
|
+
assert_equal 9, ret.length
|
313
|
+
assert_equal "asasa", ret.value
|
314
|
+
assert_equal 9, iter.pos
|
315
|
+
|
316
|
+
iter = StringInputIterator.new "a3df"
|
317
|
+
ret = p.parse iter
|
318
|
+
assert_kind_of Match, ret
|
319
|
+
assert_equal 1, ret.length
|
320
|
+
assert_equal "a", ret.value
|
321
|
+
assert_equal 1, iter.pos
|
322
|
+
|
323
|
+
iter = StringInputIterator.new "bsdf"
|
324
|
+
ret = p.parse iter
|
325
|
+
assert_kind_of NilClass, ret
|
326
|
+
assert_equal 0, iter.pos
|
327
|
+
|
328
|
+
iter = StringInputIterator.new "ssdf"
|
329
|
+
ret = p.parse iter
|
330
|
+
assert_kind_of NilClass, ret
|
331
|
+
assert_equal 0, iter.pos
|
332
|
+
end
|
333
|
+
|
334
|
+
end
|
335
|
+
|