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.
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,57 @@
1
+ # This is Spectre, a parser framework inspired by Boost.Spirit,
2
+ # which can be found at http://spirit.sourceforge.net/.
3
+ #
4
+ # If you want to find out more or need a tutorial, go to
5
+ # http://spectre.rubyforge.org/
6
+ # You'll find a nice wiki there!
7
+ #
8
+ # Author:: Fabian Streitel (karottenreibe)
9
+ # Copyright:: Copyright (c) 2009 Fabian Streitel
10
+ # License:: Boost Software License 1.0
11
+ # For further information regarding this license, you can go to
12
+ # http://www.boost.org/LICENSE_1_0.txt
13
+ # or read the file LICENSE distributed with this software.
14
+ # Homepage:: http://spectre.rubyforge.org/
15
+ # Git repo:: http://rubyforge.org/scm/?group_id=7618
16
+ #
17
+ # Keeps the standard InputIterator for String parsing.
18
+ #
19
+
20
+ require 'spectre/base/inputiterator'
21
+
22
+ module Spectre
23
+
24
+ module StringParsing
25
+
26
+ ##
27
+ # The standard input provider for Strings.
28
+ # The default transformation set will skip white-space (\s, \n, \t, \r, \f).
29
+ # This can be undone by wrapping the Parser(s) inside a +lexeme_d+.
30
+ #
31
+ class StringInputIterator < InputIterator
32
+
33
+ ##
34
+ # The default skipper for this InputIterator class.
35
+ # Skips white space.
36
+ #
37
+ def default_skipper
38
+ lambda { |token,is|
39
+ case token
40
+ when " ", "\n", "\r", "\t", "\f" then 1
41
+ else nil
42
+ end
43
+ }
44
+ end
45
+
46
+ def concat val1, val2
47
+ ( val1 || '' ) + ( val2 || '' )
48
+ end
49
+
50
+ def empty
51
+ ''
52
+ end
53
+ end
54
+
55
+ end
56
+ end
57
+
@@ -0,0 +1,400 @@
1
+ # This is Spectre, a parser framework inspired by Boost.Spirit,
2
+ # which can be found at http://spirit.sourceforge.net/.
3
+ #
4
+ # If you want to find out more or need a tutorial, go to
5
+ # http://spectre.rubyforge.org/
6
+ # You'll find a nice wiki there!
7
+ #
8
+ # Author:: Fabian Streitel (karottenreibe)
9
+ # Copyright:: Copyright (c) 2009 Fabian Streitel
10
+ # License:: Boost Software License 1.0
11
+ # For further information regarding this license, you can go to
12
+ # http://www.boost.org/LICENSE_1_0.txt
13
+ # or read the file LICENSE distributed with this software.
14
+ # Homepage:: http://spectre.rubyforge.org/
15
+ # Git repo:: http://rubyforge.org/scm/?group_id=7618
16
+ #
17
+ # Keeps the Standard Parsers for String parsing.
18
+ # Registered shortcuts for standard String Parsers:
19
+ #
20
+ # CharParser :char
21
+ # StringParser :string
22
+ # AnycharParser :any_char
23
+ # AlnumParser :alnum_char
24
+ # AlphaParser :alpha_char
25
+ # BlankParser :blank_char
26
+ # ControlParser :control_char
27
+ # DigitParser :digit
28
+ # GraphParser :graph_char
29
+ # LowerParser :lower_char
30
+ # PrintParser :print_char
31
+ # PunctParser :punct_char
32
+ # SpaceParser :space_char
33
+ # UpperParser :upper_char
34
+ # HexDigitParser :hex_digit
35
+ # EOLParser :eol
36
+ #
37
+ # See also ShortcutsMixin.
38
+ #
39
+
40
+ require 'spectre/base/parser'
41
+ require 'spectre/base/grammar'
42
+
43
+ module Spectre
44
+
45
+ module StringParsing
46
+
47
+ ##
48
+ # Matches one single character.
49
+ # Shortcut: +char+.
50
+ #
51
+ class CharParser
52
+ include Parser
53
+
54
+ def initialize char
55
+ super()
56
+ @char = char
57
+ end
58
+
59
+ def negation; Negations::NegatedSingleTokenParser.new; end
60
+
61
+ def scan iter
62
+ if iter.valid? and +iter == @char
63
+ create_match iter, @char
64
+ else
65
+ nil
66
+ end
67
+ end
68
+
69
+ def inspect
70
+ "[char:'#{@char}']"
71
+ end
72
+ end
73
+
74
+ ##
75
+ # Matches a String.
76
+ # Is an implicit lexeme, i.e. works on character level only, i.e. it will ignore any skippers set on
77
+ # the InputIterator
78
+ #
79
+ # NOTE: It's negation is a zero token parser, i.e. +~string('foo')+ will only
80
+ # test if the input at that location contains the string and return a failure if so
81
+ # and a successful match of length 0 if not.
82
+ #
83
+ # Shortcut: +string+.
84
+ #
85
+ class StringParser
86
+ include Parser
87
+
88
+ def initialize string
89
+ super()
90
+ @string = string
91
+ end
92
+
93
+ def negation; Negations::NegatedZeroTokenParser.new; end
94
+
95
+ def scan iter
96
+ return Match.new 0, @string if @string.length == 0
97
+ return nil unless iter.valid?
98
+
99
+ iter.ignore_skipper do
100
+ return create_match iter, @string if
101
+ (iter + @string.length) == @string
102
+ end
103
+
104
+ nil
105
+ end
106
+
107
+ def inspect
108
+ "[string:\"#{@string}\"]"
109
+ end
110
+ end
111
+
112
+ ##
113
+ # Matches any character, like the Regexp +/./+.
114
+ # Shortcut: +any_char+.
115
+ #
116
+ class AnycharParser
117
+ include Parser
118
+
119
+ def negation; Negations::NegatedSingleTokenParser.new; end
120
+
121
+ def scan iter
122
+ unless iter.valid?
123
+ nil
124
+ else
125
+ char = +iter
126
+ create_match iter, char
127
+ end
128
+ end
129
+
130
+ def inspect
131
+ "[any_char]"
132
+ end
133
+ end
134
+
135
+ ##
136
+ # Matches any alpha-numeric character.
137
+ # Shortcut: +alnum_char+.
138
+ #
139
+ class AlnumParser < RangeParser
140
+ def initialize
141
+ super( ('0'..'9').to_a + ('a'..'z').to_a + ('A'..'Z').to_a )
142
+ end
143
+
144
+ def inspect
145
+ "[alnum_char]"
146
+ end
147
+ end
148
+
149
+ ##
150
+ # Matches any alphabetic character.
151
+ # Shortcut: +alpha_char+.
152
+ #
153
+ class AlphaParser < RangeParser
154
+ def initialize
155
+ super( ('a'..'z').to_a + ('A'..'Z').to_a )
156
+ end
157
+
158
+ def inspect
159
+ "[alpha_char]"
160
+ end
161
+ end
162
+
163
+ ##
164
+ # Matches spaces and tabs.
165
+ # Shortcut: +blank_char+.
166
+ #
167
+ class BlankParser < RangeParser
168
+ def initialize
169
+ super([" ", "\t"])
170
+ end
171
+
172
+ def inspect
173
+ "[blank_char]"
174
+ end
175
+ end
176
+
177
+ ##
178
+ # Matches control characters.
179
+ # Shortcut: +control_char+.
180
+ #
181
+ class ControlParser < RangeParser
182
+ def initialize
183
+ super(["\0", "\a", "\b", "\t", "\n", "\f", "\r", "\e", "\s"])
184
+ end
185
+
186
+ def inspect
187
+ "[control_char]"
188
+ end
189
+ end
190
+
191
+ ##
192
+ # Matches numeric digits.
193
+ # Shortcut: +digit+.
194
+ #
195
+ class DigitParser < RangeParser
196
+ def initialize
197
+ super( ('0'..'9').to_a )
198
+ end
199
+
200
+ def inspect
201
+ "[digit]"
202
+ end
203
+ end
204
+
205
+ ##
206
+ # Matches non-space printing characters.
207
+ # Shortcut: +graph_char+.
208
+ #
209
+ class GraphParser
210
+ include Parser
211
+
212
+ def negation; Negations::NegatedSingleTokenParser.new; end
213
+
214
+ def scan iter
215
+ return nil unless iter.valid?
216
+ char = +iter
217
+
218
+ if char and char[0].between? 33, 126
219
+ create_match iter, char
220
+ else
221
+ nil
222
+ end
223
+ end
224
+
225
+ def inspect
226
+ "[graph_char]"
227
+ end
228
+ end
229
+
230
+ ##
231
+ # Matches lowercase letters.
232
+ # Shortcut: +lower_char+.
233
+ #
234
+ class LowerParser < RangeParser
235
+ def initialize
236
+ super( ('a'..'z').to_a )
237
+ end
238
+
239
+ def inspect
240
+ "[lower_char]"
241
+ end
242
+ end
243
+
244
+ ##
245
+ # Matches printable characters.
246
+ # Shortcut: +print_char+.
247
+ #
248
+ class PrintParser
249
+ include Parser
250
+
251
+ class << self
252
+ def negation; Negations::NegatedSingleTokenParser.new; end
253
+ end
254
+
255
+ def scan iter
256
+ return nil unless iter.valid?
257
+ char = +iter
258
+
259
+ if char and char[0].between? 32, 126
260
+ create_match iter, char
261
+ else
262
+ nil
263
+ end
264
+ end
265
+
266
+ def inspect
267
+ "[print_char]"
268
+ end
269
+ end
270
+
271
+ ##
272
+ # Matches punctuation symbols.
273
+ # Shortcut: +punct_char+.
274
+ #
275
+ class PunctParser
276
+ include Parser
277
+
278
+ class << self
279
+ def negation; Negations::NegatedSingleTokenParser.new; end
280
+ end
281
+
282
+ def scan iter
283
+ return nil unless iter.valid?
284
+ char = +iter
285
+
286
+ if char and ( char[0].between? 33, 126 ) and ( not ('a'..'z').include? char ) and
287
+ ( not ('A'..'Z').include? char ) and ( not ('0'..'9').include? char )
288
+ create_match iter, char
289
+ else
290
+ nil
291
+ end
292
+ end
293
+
294
+ def inspect
295
+ "[punct_char]"
296
+ end
297
+ end
298
+
299
+ ##
300
+ # Matches spaces, tabs, returns and newlines.
301
+ # Shortcut: +space_char+.
302
+ #
303
+ class SpaceParser < RangeParser
304
+ def initialize
305
+ super([" ", "\t", "\n", "\r"])
306
+ end
307
+
308
+ def inspect
309
+ "[space_char]"
310
+ end
311
+ end
312
+
313
+ ##
314
+ # Matches uppercase letters.
315
+ # Shortcut: +upper_char+.
316
+ #
317
+ class UpperParser < RangeParser
318
+ def initialize
319
+ super( ('A'..'Z').to_a )
320
+ end
321
+
322
+ def inspect
323
+ "[upper_char]"
324
+ end
325
+ end
326
+
327
+ ##
328
+ # Matches hexadecimal digits.
329
+ # Shortcut: +hex_digit+.
330
+ #
331
+ class HexDigitParser < RangeParser
332
+ def initialize
333
+ super( ('0'..'9').to_a + ('a'..'f').to_a + ('A'..'F').to_a )
334
+ end
335
+
336
+ def inspect
337
+ "[hex_digit]"
338
+ end
339
+ end
340
+
341
+ ##
342
+ # Matches any end-of-line characters (CR/LF) and combinations thereof.
343
+ # Shortcut: +eol+.
344
+ #
345
+ class EOLParser
346
+ include Parser
347
+
348
+ class << self
349
+ def negation; Negations::NegatedZeroTokenParser.new; end
350
+ end
351
+
352
+ def scan iter
353
+ return nil unless iter.valid?
354
+ buf = nil
355
+
356
+ while iter.valid? and ["\n", "\r"].include? iter.get
357
+ buf = iter.concat(buf, +iter)
358
+ end
359
+
360
+ if buf then create_match iter, buf
361
+ else nil
362
+ end
363
+ end
364
+
365
+ def inspect
366
+ "[EOL]"
367
+ end
368
+ end
369
+
370
+ ShortcutsMixin.register_shortcut( {
371
+ :char => CharParser,
372
+ :string => StringParser,
373
+ :any_char => AnycharParser,
374
+ :alnum_char => AlnumParser,
375
+ :alpha_char => AlphaParser,
376
+ :blank_char => BlankParser,
377
+ :control_char => ControlParser,
378
+ :digit => DigitParser,
379
+ :graph_char => GraphParser,
380
+ :lower_char => LowerParser,
381
+ :print_char => PrintParser,
382
+ :punct_char => PunctParser,
383
+ :space_char => SpaceParser,
384
+ :upper_char => UpperParser,
385
+ :hex_digit => HexDigitParser,
386
+ :eol => EOLParser,
387
+ } )
388
+
389
+ end
390
+
391
+ end
392
+
393
+ ##
394
+ # Register String as a POD with the CharParser and StringParser.
395
+ Spectre::register_POD(String) do |str|
396
+ str.length == 1 ?
397
+ Spectre::StringParsing::CharParser.new(str) :
398
+ Spectre::StringParsing::StringParser.new(str)
399
+ end
400
+