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,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
+