Spectre 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/CHANGELOG +1 -0
  2. data/LICENSE +23 -0
  3. data/README +20 -0
  4. data/Rakefile +112 -0
  5. data/lib/spectre/base.rb +44 -0
  6. data/lib/spectre/base/closure.rb +96 -0
  7. data/lib/spectre/base/directive.rb +148 -0
  8. data/lib/spectre/base/grammar.rb +269 -0
  9. data/lib/spectre/base/inputiterator.rb +276 -0
  10. data/lib/spectre/base/node.rb +393 -0
  11. data/lib/spectre/base/operators.rb +342 -0
  12. data/lib/spectre/base/parser.rb +110 -0
  13. data/lib/spectre/generic.rb +115 -0
  14. data/lib/spectre/generic/directives.rb +246 -0
  15. data/lib/spectre/generic/negations.rb +68 -0
  16. data/lib/spectre/generic/primitives.rb +172 -0
  17. data/lib/spectre/generic/semanticaction.rb +43 -0
  18. data/lib/spectre/string.rb +57 -0
  19. data/lib/spectre/string/additionals.rb +80 -0
  20. data/lib/spectre/string/directives.rb +51 -0
  21. data/lib/spectre/string/inputiterator.rb +57 -0
  22. data/lib/spectre/string/primitives.rb +400 -0
  23. data/test/base/closure_tests.rb +108 -0
  24. data/test/base/grammar_tests.rb +97 -0
  25. data/test/base/operator_tests.rb +335 -0
  26. data/test/base/semanticaction_tests.rb +53 -0
  27. data/test/generic/directive_tests.rb +224 -0
  28. data/test/generic/negation_tests.rb +146 -0
  29. data/test/generic/primitive_tests.rb +99 -0
  30. data/test/string/POD2Parser_tests.rb +93 -0
  31. data/test/string/additional_tests.rb +43 -0
  32. data/test/string/directive_tests.rb +32 -0
  33. data/test/string/primitive_tests.rb +173 -0
  34. data/test/tests.rb +33 -0
  35. data/test/tutorial/funnymath_tests.rb +57 -0
  36. data/test/tutorial/html_tests.rb +171 -0
  37. data/test/tutorial/skipping_tests.rb +60 -0
  38. metadata +109 -0
@@ -0,0 +1,53 @@
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 SemanticActionTests < Test::Unit::TestCase
24
+ include Spectre
25
+ include Spectre::StringParsing
26
+ include Spectre::ShortcutsMixin
27
+
28
+ def setup
29
+ @tag_grammar = Grammar.new do ||
30
+ rule :tag => lexeme_d['<'.to_p >> blank_char >> :tagname.to_p[:tag] >> '>']
31
+ rule :tagname => ( ~char('>') ).+
32
+ rule :border => :tag
33
+ start_with :tag
34
+ end
35
+ end
36
+
37
+ def testSimpleAction
38
+ val = 0
39
+ a = lambda { val = 22 }
40
+ p = any_char[a]
41
+
42
+ ret = parse 'a', p
43
+ assert_equal 1, ret.length
44
+ assert_equal 'a', ret.value
45
+ assert_equal val, 22
46
+ end
47
+
48
+ def testClosureAction
49
+ c = @tag_grammar.closure = Closure.new
50
+ ret = parse '< foo>', @tag_grammar
51
+ assert_equal 'foo', c[:tag]
52
+ end
53
+ end
@@ -0,0 +1,224 @@
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 DirectiveTests < Test::Unit::TestCase
24
+ include Spectre
25
+ include Spectre::StringParsing
26
+ include Spectre::ShortcutsMixin
27
+
28
+ def testNoActionD
29
+ val = 1
30
+
31
+ tester = lambda { |m,c|
32
+ val += 12
33
+ }
34
+
35
+ p = noaction_d[any_char[tester]]
36
+ ret = parse 'aaa', p
37
+ assert_kind_of Match, ret
38
+ assert_equal 1, val
39
+ assert_equal "a", ret.value
40
+ end
41
+
42
+ def testResetD
43
+ val = 1
44
+
45
+ tester = lambda { |m,c|
46
+ val += 12
47
+ }
48
+
49
+ p = noaction_d[reset_d[any_char[tester]]]
50
+ ret = parse 'aa', p
51
+ assert_kind_of Match, ret
52
+ assert_equal 13, val
53
+ end
54
+
55
+ class Limit
56
+ include Comparable
57
+
58
+ def initialize fn
59
+ @fn = fn
60
+ end
61
+
62
+ def <=> s
63
+ @fn <=> s.length
64
+ end
65
+ end
66
+
67
+ def testLimitD
68
+ p = limit_d(Limit.new(2),Limit.new(4))[any_char.*]
69
+ ret = parse 'aa', p
70
+ assert_kind_of Match, ret
71
+ ret = parse 'aaa', p
72
+ assert_kind_of Match, ret
73
+ ret = parse 'aaaa', p
74
+ assert_kind_of Match, ret
75
+ ret = parse 'a', p
76
+ assert_kind_of NilClass, ret
77
+ ret = parse 'aaaaa', p
78
+ assert_kind_of NilClass, ret
79
+ end
80
+
81
+ def testSkipD
82
+ p = skip_d(['a', 'b', 'c'].to_p)[blank_char >> any_char]
83
+
84
+ ret = parse ' u', p
85
+ assert_kind_of Match, ret
86
+ assert_equal 2, ret.length
87
+
88
+ ret = parse 'abcabc abcu', p
89
+ assert_kind_of Match, ret
90
+ assert_equal 11, ret.length
91
+
92
+ p = skip_d(["\n", "\r", "\t", "\f", " "].to_p)[char("a") >> any_char]
93
+ ret = parse " \n \r a \t\fu ", p
94
+ assert_kind_of Match, ret
95
+ end
96
+
97
+ class SP < StringParser
98
+ class << self
99
+ attr_accessor :val
100
+
101
+ def new *args
102
+ Spectre::Node.new super(*args)
103
+ end
104
+ end
105
+
106
+ def scan *args
107
+ SP.val += 1
108
+ super(*args)
109
+ end
110
+ end
111
+
112
+ def testLongestD
113
+ SP.val = 0
114
+ p = longest_d[SP.new('a')|SP.new('ab')|SP.new('aac')]
115
+ ret = parse "aac", p
116
+ assert_equal 3, SP.val
117
+ assert_kind_of Match, ret
118
+ assert_equal "aac", ret.value
119
+
120
+ SP.val = 0
121
+ ret = parse "ab", p
122
+ assert_equal 3, SP.val
123
+ assert_kind_of Match, ret
124
+ assert_equal "ab", ret.value
125
+
126
+ SP.val = 0
127
+ ret = parse "a", p
128
+ assert_equal 3, SP.val
129
+ assert_kind_of Match, ret
130
+ assert_equal "a", ret.value
131
+ end
132
+
133
+ def testShortestD
134
+ SP.val = 0
135
+ p = shortest_d[SP.new('a')|SP.new('ab')|SP.new('cac')]
136
+ ret = parse "cac", p
137
+ assert_equal 3, SP.val
138
+ assert_kind_of Match, ret
139
+ assert_equal "cac", ret.value
140
+
141
+ SP.val = 0
142
+ ret = parse "ab", p
143
+ assert_equal 3, SP.val
144
+ assert_kind_of Match, ret
145
+ assert_equal "a", ret.value
146
+
147
+ SP.val = 0
148
+ ret = parse "a", p
149
+ assert_equal 3, SP.val
150
+ assert_kind_of Match, ret
151
+ assert_equal "a", ret.value
152
+ end
153
+
154
+ def testLexemeD
155
+ p = noskip_d[char('a') >> char('b')]
156
+ p = lexeme_d[char('a') >> char('b')]
157
+ ret = parse "ab", p
158
+ assert_kind_of Match, ret
159
+ assert_equal "ab", ret.value
160
+ assert_equal 2, ret.length
161
+
162
+ ret = parse " ab", p
163
+ assert_kind_of Match, ret
164
+ assert_equal "ab", ret.value
165
+ assert_equal 3, ret.length
166
+
167
+ ret = parse "a b", p
168
+ assert_kind_of NilClass, ret
169
+
170
+ p = char('o') >> lexeme_d[char('a') >> char('b')]
171
+ ret = parse "o ab", p
172
+ assert_kind_of Match, ret
173
+ assert_equal "oab", ret.value
174
+ assert_equal 4, ret.length
175
+
176
+ ret = parse "oab", p
177
+ assert_kind_of Match, ret
178
+ assert_equal "oab", ret.value
179
+ assert_equal 3, ret.length
180
+ end
181
+
182
+ def testNoPreSkipLexemeD
183
+ p = noskip_d![char('a') >> char('b')]
184
+ p = lexeme_d![char('a') >> char('b')]
185
+ ret = parse "ab", p
186
+ assert_kind_of Match, ret
187
+ assert_equal "ab", ret.value
188
+ assert_equal 2, ret.length
189
+
190
+ ret = parse "a b", p
191
+ assert_kind_of NilClass, ret
192
+
193
+ ret = parse " ab", p
194
+ assert_kind_of NilClass, ret
195
+
196
+ p = char('o') >> lexeme_d![char('a') >> char('b')]
197
+ ret = parse "o ab", p
198
+ assert_kind_of NilClass, ret
199
+
200
+ ret = parse "oab", p
201
+ assert_kind_of Match, ret
202
+ assert_equal "oab", ret.value
203
+ assert_equal 3, ret.length
204
+ end
205
+
206
+ def testEpsilonD
207
+ p = epsilon[string("foo")]
208
+ p = e[string("foo")]
209
+ ret = parse "foo", p
210
+ assert_kind_of Match, ret
211
+ assert_equal 0, ret.length
212
+ assert_equal "foo", ret.value
213
+
214
+ ret = parse " foo", p
215
+ assert_kind_of Match, ret
216
+ assert_equal 0, ret.length
217
+ assert_equal "foo", ret.value
218
+
219
+ ret = parse "bar", p
220
+ assert_kind_of NilClass, ret
221
+ end
222
+
223
+ end
224
+
@@ -0,0 +1,146 @@
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 GenericNegationTests < Test::Unit::TestCase
24
+ include Spectre
25
+ include Spectre::Operators
26
+ include Spectre::StringParsing
27
+
28
+ def testSingleTokenNegation
29
+ p = Node.new Negation.new, CharParser.new("a")
30
+ iter = StringInputIterator.new "asdf"
31
+ ret = p.parse iter
32
+ assert_kind_of NilClass, ret
33
+ assert_equal 0, iter.pos
34
+
35
+ iter = StringInputIterator.new "33df"
36
+ ret = p.parse iter
37
+ assert_kind_of Match, ret
38
+ assert_equal 1, ret.length
39
+ assert_equal "3", ret.value
40
+ assert_equal 1, iter.pos
41
+
42
+ iter = StringInputIterator.new " 33df"
43
+ ret = p.parse iter
44
+ assert_kind_of Match, ret
45
+ assert_equal 3, ret.length
46
+ assert_equal "3", ret.value
47
+ assert_equal 3, iter.pos
48
+
49
+ iter = StringInputIterator.new "\tdf"
50
+ ret = p.parse iter
51
+ assert_kind_of Match, ret
52
+ assert_equal 2, ret.length
53
+ assert_equal "d", ret.value
54
+ assert_equal 2, iter.pos
55
+ end
56
+
57
+ def testZeroTokenNegation
58
+ p = Node.new Negation.new, EOIParser.new
59
+ iter = StringInputIterator.new " asdf"
60
+ ret = p.parse iter, false
61
+ assert_kind_of Match, ret
62
+ assert_equal 0, ret.length
63
+ assert_equal "", ret.value
64
+ assert_equal 0, iter.pos
65
+
66
+ iter = StringInputIterator.new " "
67
+ ret = p.parse iter
68
+ assert_kind_of NilClass, ret
69
+ assert_equal 0, iter.pos
70
+
71
+ iter = StringInputIterator.new ""
72
+ ret = p.parse iter
73
+ assert_kind_of NilClass, ret
74
+ assert_equal 0, iter.pos
75
+ end
76
+
77
+ def testSequenceNegation
78
+ p = Node.new Negation.new, SequenceParser.new("foa")
79
+ iter = StringInputIterator.new " a of"
80
+ ret = p.parse iter
81
+ assert_kind_of Match, ret
82
+ assert_equal 1, ret.length
83
+ assert_equal "", ret.value
84
+ assert_equal 1, iter.pos
85
+
86
+ iter = StringInputIterator.new " "
87
+ ret = p.parse iter, false
88
+ assert_kind_of Match, ret
89
+ assert_equal 0, ret.length
90
+ assert_equal "", ret.value
91
+ assert_equal 0, iter.pos
92
+
93
+ iter = StringInputIterator.new "fo a"
94
+ ret = p.parse iter
95
+ assert_kind_of NilClass, ret
96
+ assert_equal 0, iter.pos
97
+ end
98
+
99
+ def testStringNegation
100
+ p = Node.new Negation.new, StringParser.new("foo")
101
+ iter = StringInputIterator.new " asdf"
102
+ ret = p.parse iter
103
+ assert_kind_of Match, ret
104
+ assert_equal 1, ret.length
105
+ assert_equal "", ret.value
106
+ assert_equal 1, iter.pos
107
+
108
+ iter = StringInputIterator.new " "
109
+ ret = p.parse iter, false
110
+ assert_kind_of Match, ret
111
+ assert_equal 0, ret.length
112
+ assert_equal "", ret.value
113
+ assert_equal 0, iter.pos
114
+
115
+ iter = StringInputIterator.new "foo"
116
+ ret = p.parse iter
117
+ assert_kind_of NilClass, ret
118
+ assert_equal 0, iter.pos
119
+ end
120
+
121
+ def testClosureParserNegation
122
+ gram = Grammar.new do ||
123
+ start_with close( lower_char[:foo] >> ~closed(:foo) )
124
+ end
125
+
126
+ iter = StringInputIterator.new 'ab'
127
+ ret = gram.parse iter
128
+ assert_kind_of Match, ret
129
+ assert_equal 2, ret.length
130
+ assert_equal "ab", ret.value
131
+ assert_equal 2, iter.pos
132
+
133
+ iter = StringInputIterator.new ' ab'
134
+ ret = gram.parse iter
135
+ assert_kind_of Match, ret
136
+ assert_equal 4, ret.length
137
+ assert_equal "ab", ret.value
138
+ assert_equal 4, iter.pos
139
+
140
+ iter = StringInputIterator.new ' aa'
141
+ ret = gram.parse iter
142
+ assert_kind_of NilClass, ret
143
+ end
144
+
145
+ end
146
+
@@ -0,0 +1,99 @@
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 StringPrimitivesTests < Test::Unit::TestCase
24
+ include Spectre
25
+ include Spectre::StringParsing
26
+ include Spectre::ShortcutsMixin
27
+
28
+ def testRangeParser
29
+ p = RangeParser.new "a".."c"
30
+ ret = parse "a", p
31
+ assert_kind_of Match, ret
32
+ assert_equal 1, ret.length
33
+ assert_equal "a", ret.value
34
+
35
+ ret = parse "chunky", p
36
+ assert_kind_of Match, ret
37
+ assert_equal 1, ret.length
38
+ assert_equal "c", ret.value
39
+
40
+ ret = parse "1", p
41
+ assert_kind_of NilClass, ret
42
+
43
+ ret = parse "zba", p
44
+ assert_kind_of NilClass, ret
45
+
46
+ ret = parse "", p
47
+ assert_kind_of NilClass, ret
48
+ end
49
+
50
+ def testSequenceParser
51
+ p = SequenceParser.new "chunky".split("")
52
+ ret = parse "chunky-b", p
53
+ assert_kind_of Match, ret
54
+ assert_equal 6, ret.length
55
+ assert_equal "chunky", ret.value
56
+
57
+ ret = parse "chunky", p
58
+ assert_kind_of Match, ret
59
+ assert_equal 6, ret.length
60
+ assert_equal "chunky", ret.value
61
+
62
+ ret = parse "\tc h u\nnk y\f", p
63
+ assert_kind_of Match, ret
64
+ assert_equal 12, ret.length
65
+ assert_equal "chunky", ret.value
66
+
67
+ ret = parse "z", p
68
+ assert_kind_of NilClass, ret
69
+
70
+ ret = parse "", p
71
+ assert_kind_of NilClass, ret
72
+ end
73
+
74
+ def testNothingParser
75
+ p = NothingParser.new
76
+ ret = parse "asdf", p
77
+ assert_kind_of NilClass, ret
78
+
79
+ ret = parse "", p
80
+ assert_kind_of NilClass, ret
81
+ end
82
+
83
+ def testEOIParser
84
+ p = EOIParser.new
85
+ ret = parse "asdf", p
86
+ assert_kind_of NilClass, ret
87
+
88
+ ret = parse "", p
89
+ assert_kind_of Match, ret
90
+ assert_equal 0, ret.length
91
+ assert_equal "", ret.value
92
+
93
+ ret = parse " ", p
94
+ assert_kind_of Match, ret
95
+ assert_equal 0, ret.length
96
+ assert_equal "", ret.value
97
+ end
98
+ end
99
+