yaparc 0.2.0 → 0.2.2

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 (4) hide show
  1. data/README +13 -0
  2. data/lib/yaparc.rb +157 -95
  3. data/tests/test_parser.rb +49 -20
  4. metadata +2 -2
data/README CHANGED
@@ -136,6 +136,19 @@ The ManyOne requires at least one successfull application of parser.
136
136
  * Symbol
137
137
 
138
138
 
139
+ == Regex parser
140
+
141
+ parser = Regex.new(/\A[0-9]+/)
142
+ result = parser.parse("1234ab")
143
+ assert_equal '1234', result.value
144
+
145
+ parser = Regex.new(/([0-9]+):([a-z]+)/) do |match1, match2|
146
+ [match2,match1]
147
+ end
148
+ result = parser.parse("1234:ab")
149
+ assert_equal ["ab", "1234"], result.value
150
+
151
+
139
152
  == Define your own parser
140
153
 
141
154
  In order to construct parsers, you make parser class to be inherited from Yaparc::AbstractParser class.
data/lib/yaparc.rb CHANGED
@@ -27,41 +27,55 @@ module Yaparc
27
27
  IS_DIGIT = lambda {|i| i >= '0' and i <= '9'}
28
28
  IS_SPACE = lambda {|i| i == ' '}
29
29
  IS_WHITESPACE = lambda {|i| i == ' ' or i == "\n" or i == "\t"}
30
+ IS_CR = lambda {|i| i == "\n"}
30
31
 
31
- def self.included(mod)
32
- mod.extend ClassMethods
33
- end
32
+ # def self.included(mod)
33
+ # mod.extend ClassMethods
34
+ # end
34
35
 
35
- def parse(input, &block)
36
+ def parse(input) #, &block)
36
37
  result = @parser.call(input)
37
38
 
38
- if result.respond_to? :parse
39
- result = result.parse(input)
39
+ if result.respond_to?(:parse)
40
+ result.parse(input)
40
41
  else
41
- if block_given?
42
- result.value = yield result.value
43
- @tree = result
44
- else
45
- @tree = result.value
46
- end
47
42
  result
48
43
  end
49
- end
50
44
 
51
- def eval
52
- tree = parse(input)
45
+ # if result.respond_to? :parse
46
+ # result = result.parse(input)
47
+ # else
48
+ # # if block_given?
49
+ # # result.value = yield result.value
50
+ # # @tree = result
51
+ # # end
52
+ # result
53
+ # end
54
+
55
+ # if result.respond_to? :parse
56
+ # result = result.parse(input)
57
+ # else
58
+ # if block_given?
59
+ # result.value = yield result.value
60
+ # @tree = result
61
+ # else
62
+ # @tree = result.value
63
+ # end
64
+ # result
65
+ # end
53
66
  end
54
67
 
55
-
56
- module ClassMethods
57
- def included(mod)
58
- end
59
- end
60
- end # of Module Parsable
68
+ # def eval
69
+ # tree = parse(input)
70
+ # end
61
71
 
62
72
 
73
+ # module ClassMethods
74
+ # def included(mod)
75
+ # end
76
+ # end
77
+ end # of Module Parsable
63
78
 
64
- # class SucceedParser
65
79
  class Succeed
66
80
  include Parsable
67
81
  attr_reader :remaining
@@ -73,7 +87,6 @@ module Yaparc
73
87
  end
74
88
  end
75
89
 
76
- # class FailParser
77
90
  class Fail
78
91
  include Parsable
79
92
  def initialize
@@ -84,8 +97,6 @@ module Yaparc
84
97
  end
85
98
 
86
99
 
87
-
88
- # class ItemParser
89
100
  class Item
90
101
  include Parsable
91
102
  def initialize
@@ -99,7 +110,6 @@ module Yaparc
99
110
  end
100
111
  end
101
112
 
102
- # class ZeroOneParser
103
113
  class ZeroOne
104
114
  include Parsable
105
115
  def initialize(parser, identity = [])
@@ -115,36 +125,43 @@ module Yaparc
115
125
  else
116
126
  raise
117
127
  end
118
-
119
- # AltParser.new(parser, Succeed.new(identity))
120
- # case result = AltParser.new(parser, Succeed.new(identity)).parse(input)
121
- # if input.nil? or input.empty?
122
- # Result::Fail.new(:input => input)
123
- # else
124
- # Result::OK.new(:value => input[0..0],:input => input[1..input.length])
125
- # end
126
-
127
128
  end
128
129
  end
129
130
  end
130
131
 
131
- # class SatisfyParser
132
132
  class Satisfy
133
133
  include Parsable
134
134
  def initialize(predicate)
135
135
  raise unless predicate.instance_of?(Proc)
136
136
 
137
137
  @parser = lambda do |input|
138
- case result = Item.new.parse(input)
139
- when Result::OK
140
- parser = if predicate.call(result.value)
141
- Succeed.new(result.value, result.input)
142
- else
143
- Fail.new
144
- end
145
- else # Result::Fail or Result::Error
138
+ result = Item.new.parse(input)
139
+ if result.instance_of?(Result::OK) and predicate.call(result.value)
140
+ Succeed.new(result.value, result.input)
141
+ else
146
142
  Fail.new
147
143
  end
144
+
145
+ # if result.instance_of?(Result::OK)
146
+ # if predicate.call(result.value)
147
+ # Succeed.new(result.value, result.input)
148
+ # else
149
+ # Fail.new
150
+ # end
151
+ # else # Result::Fail or Result::Error
152
+ # Fail.new
153
+ # end
154
+
155
+ # case result = Item.new.parse(input)
156
+ # when Result::OK
157
+ # parser = if predicate.call(result.value)
158
+ # Succeed.new(result.value, result.input)
159
+ # else
160
+ # Fail.new
161
+ # end
162
+ # else # Result::Fail or Result::Error
163
+ # Fail.new
164
+ # end
148
165
  end
149
166
  end
150
167
 
@@ -167,21 +184,26 @@ module Yaparc
167
184
 
168
185
  def initialize(parser, &block)
169
186
  @parser = lambda do |input|
170
- case result = parser.parse(input)
171
- when Result::Fail
187
+ result = parser.parse(input)
188
+ if result.instance_of?(Result::Fail)
172
189
  Result::Error.new(:value => result.value, :input => result.input)
173
- when Result::OK
174
- Succeed.new(result.value)
175
190
  else
176
191
  Succeed.new(result.value)
177
- # Result::OK.new(:value => result.value,:input => result.input)
178
192
  end
193
+ # case result = parser.parse(input)
194
+ # when Result::Fail
195
+ # Result::Error.new(:value => result.value, :input => result.input)
196
+ # when Result::OK
197
+ # Succeed.new(result.value)
198
+ # else
199
+ # Succeed.new(result.value)
200
+ # # Result::OK.new(:value => result.value,:input => result.input)
201
+ # end
179
202
  end
180
203
  end
181
204
  end # of NoFail
182
205
 
183
206
 
184
- # class SeqParser
185
207
  class Seq
186
208
  include Parsable
187
209
  def initialize(*parsers, &block)
@@ -189,15 +211,20 @@ module Yaparc
189
211
  args = []
190
212
  initial_result = Result::OK.new(:input => input)
191
213
  final_result = parsers.inject(initial_result) do |subsequent, parser|
192
- case result = parser.parse(subsequent.input)
193
- when Result::Fail
214
+ result = parser.parse(subsequent.input)
215
+ if result.instance_of?(Result::Fail)
194
216
  break Result::Fail.new(:input => subsequent.input)
195
- # when Result::Error
196
- # break Result::Error.new(:input => subsequent.input)
197
217
  else
198
218
  args << result.value
199
219
  result
200
220
  end
221
+ # case result = parser.parse(subsequent.input)
222
+ # when Result::Fail
223
+ # break Result::Fail.new(:input => subsequent.input)
224
+ # else
225
+ # args << result.value
226
+ # result
227
+ # end
201
228
  end
202
229
 
203
230
  case final_result
@@ -217,21 +244,18 @@ module Yaparc
217
244
  end # of initialize
218
245
  end # of Seq
219
246
 
220
-
221
- # class AltParser
222
247
  class Alt
223
248
  include Parsable
224
249
  def initialize(*parsers)
225
250
  @parser = lambda do |input|
226
- initial_result = Result::OK.new(:input => input)
227
251
  final_result = Result::Fail.new(:input => input)
228
252
  parsers.each do |parser|
229
- # case result = parser.parse(initial_result.input)
230
253
  case result = parser.parse(input)
231
254
  when Result::Fail
232
255
  next
233
- when Result::Error
234
- return Result::Error.new(:value => result.value, :input => result.input)
256
+ # when Result::Error
257
+ # raise
258
+ # return Result::Error.new(:value => result.value, :input => result.input)
235
259
  when Result::OK
236
260
  break final_result = result
237
261
  else
@@ -243,17 +267,22 @@ module Yaparc
243
267
  end # of initialize
244
268
  end
245
269
 
246
- # class ApplyParser
247
270
  class Apply
248
271
  include Parsable
249
272
  def initialize(parser, &block)
250
273
  @parser = lambda do |input|
251
- case result = parser.parse(input)
252
- when Result::OK
274
+ result = parser.parse(input)
275
+ if result.instance_of?(Result::OK)
253
276
  Succeed.new(yield(result.value)).parse(result.input)
254
277
  else
255
278
  Fail.new.parse(input)
256
279
  end
280
+ # case result = parser.parse(input)
281
+ # when Result::OK
282
+ # Succeed.new(yield(result.value)).parse(result.input)
283
+ # else
284
+ # Fail.new.parse(input)
285
+ # end
257
286
  end
258
287
  end # of initialize
259
288
  end # of Apply
@@ -261,13 +290,13 @@ module Yaparc
261
290
 
262
291
  class String
263
292
  include Parsable
264
- def initialize(string)
293
+ def initialize(string, case_sensitive = true)
265
294
  @parser = lambda do |input|
266
- case result = Item.new.parse(string)
267
- when Result::OK
295
+ result = Item.new.parse(string)
296
+ if result.instance_of?(Result::OK)
268
297
  Seq.new(
269
- Char.new(result.value),
270
- Yaparc::String.new(result.input),
298
+ Char.new(result.value, case_sensitive),
299
+ Yaparc::String.new(result.input, case_sensitive),
271
300
  Succeed.new(result.value + result.input)
272
301
  ) do |char_result, string_result, succeed_result|
273
302
  succeed_result
@@ -275,6 +304,18 @@ module Yaparc
275
304
  else
276
305
  Succeed.new(result) # Is it OK?
277
306
  end
307
+ # case result = Item.new.parse(string)
308
+ # when Result::OK
309
+ # Seq.new(
310
+ # Char.new(result.value, case_sensitive),
311
+ # Yaparc::String.new(result.input, case_sensitive),
312
+ # Succeed.new(result.value + result.input)
313
+ # ) do |char_result, string_result, succeed_result|
314
+ # succeed_result
315
+ # end
316
+ # else
317
+ # Succeed.new(result) # Is it OK?
318
+ # end
278
319
  end
279
320
  end
280
321
 
@@ -283,10 +324,9 @@ module Yaparc
283
324
  # end
284
325
  end
285
326
 
286
- # class RegexParser
287
327
  class Regex
288
328
  include Parsable
289
-
329
+
290
330
  def initialize(regex, &block)
291
331
  @regex = regex
292
332
  @parser = lambda do |input|
@@ -303,6 +343,7 @@ module Yaparc
303
343
  end
304
344
 
305
345
  def parse_with_parameter(input)
346
+ raise "Deprecated!! Use Regex with block"
306
347
  if match = Regexp.new(@regex).match(input)
307
348
  if block_given?
308
349
  yield match.to_a[1..match.to_a.length]
@@ -316,7 +357,6 @@ module Yaparc
316
357
  end
317
358
 
318
359
  # permits zero or more applications of parser.
319
- # class ManyParser
320
360
  class Many
321
361
  include Parsable
322
362
  def initialize(parser, identity = [])
@@ -327,7 +367,6 @@ module Yaparc
327
367
  end
328
368
 
329
369
  # requires at least one successfull application of parser.
330
- # class ManyOne
331
370
  class ManyOne
332
371
  include Parsable
333
372
  def initialize(parser, identity = [])
@@ -338,41 +377,53 @@ module Yaparc
338
377
  if tail.instance_of?(::String)
339
378
  head + tail
340
379
  else
341
- raise "Incompatible type: head => #{head}, tail => #{tail}"
380
+ raise "Incompatible type: head => #{head.inspect}, tail => #{tail.inspect}"
342
381
  end
343
382
  when ::Array
344
383
  if tail.instance_of?(Array)
345
384
  head + tail
346
385
  else
347
- raise "Incompatible type: head => #{head}, tail => #{tail}"
386
+ raise "Incompatible type: head => #{head.inspect}, tail => #{tail.inspect}"
348
387
  end
349
388
  when ::Hash
350
389
  if tail.instance_of?(Hash)
351
390
  head.merge(tail)
352
391
  else
353
- raise "Incompatible type: head => #{head}, tail => #{tail}"
392
+ raise "Incompatible type: head => #{head.inspect}, tail => #{tail.inspect}"
354
393
  end
355
394
  when ::Integer
356
395
  if tail.kind_of?(Integer)
357
396
  head + tail
358
397
  else
359
- raise "Incompatible type: head => #{head}, tail => #{tail}"
398
+ raise "Incompatible type: head => #{head.inspect}, tail => #{tail.inspect}"
360
399
  end
361
400
  else
362
- raise "Incompatible type: head => #{head}"
401
+ if tail.nil?
402
+ head
403
+ else
404
+ [head] + tail
405
+ end
363
406
  end
364
- #head + tail
365
407
  end
366
408
  end
367
409
  end
368
410
  end
369
411
 
370
- # class SpaceParser
371
412
  class Space
372
413
  include Parsable
373
414
  def initialize
374
415
  @parser = lambda do |input|
375
- Seq.new(Many.new(Satisfy.new(IS_SPACE),""))
416
+ #Many.new(Satisfy.new(IS_SPACE),"")
417
+ Regex.new(/\A[ ]*/)
418
+ end
419
+ end
420
+ end
421
+
422
+ class CR
423
+ include Parsable
424
+ def initialize
425
+ @parser = lambda do |input|
426
+ Regex.new(/\A[ \t]+[\n][ \t\n]+/)
376
427
  end
377
428
  end
378
429
  end
@@ -381,7 +432,8 @@ module Yaparc
381
432
  include Parsable
382
433
  def initialize
383
434
  @parser = lambda do |input|
384
- Seq.new(Many.new(Satisfy.new(IS_WHITESPACE),''))
435
+ #Many.new(Satisfy.new(IS_WHITESPACE),'')
436
+ Regex.new(/\A[\t\n ]*/)
385
437
  end
386
438
  end
387
439
  end
@@ -392,7 +444,7 @@ module Yaparc
392
444
 
393
445
  def initialize(parser, args = { }, &block)
394
446
  @parser = lambda do |input|
395
- @prefix = args[:prefix] ? args[:prefix] : WhiteSpace.new
447
+ @prefix = args[:prefix] ? args[:prefix] : WhiteSpace.new
396
448
  @postfix = args[:postfix] ? args[:postfix] : WhiteSpace.new
397
449
  if block_given?
398
450
  yield self
@@ -408,18 +460,16 @@ module Yaparc
408
460
  end
409
461
  end
410
462
 
411
- # class LiteralParser
412
463
  class Literal
413
464
  include Parsable
414
- def initialize(literal)
465
+ def initialize(literal, case_sensitive = true)
415
466
  @parser = lambda do |input|
416
- Tokenize.new(Yaparc::String.new(literal))
467
+ Tokenize.new(Yaparc::String.new(literal, case_sensitive))
417
468
  end
418
469
  end
419
470
  end
420
471
 
421
472
  # Refer to http://www.cs.nott.ac.uk/~gmh/monparsing.pdf, p.23
422
-
423
473
  class Identifier
424
474
  include Yaparc::Parsable
425
475
  @@identifier_regex = ::Yaparc::Regex.new(/\A[a-zA-Z_]+[a-zA-Z0-9_]*/)
@@ -442,17 +492,21 @@ module Yaparc
442
492
  end
443
493
  end
444
494
 
445
- def parse(input)
446
- @parser.call(input).parse(input)
447
- end
495
+ # def parse(input)
496
+ # @parser.call(input).parse(input)
497
+ # end
448
498
  end
449
499
 
450
- # class Char
451
500
  class Char
452
501
  include Parsable
453
502
 
454
- def initialize(char)
455
- equal_char = lambda {|i| i == char}
503
+ def initialize(char, case_sensitive = true)
504
+ raise unless char.length == 1
505
+ if case_sensitive
506
+ equal_char = lambda {|i| i == char}
507
+ else # in case of case-insentive
508
+ equal_char = lambda {|i| i.casecmp(char) == 0}
509
+ end
456
510
  @parser = lambda do |input|
457
511
  Satisfy.new(equal_char)
458
512
  end
@@ -464,9 +518,9 @@ module Yaparc
464
518
  def initialize
465
519
  @parser = lambda do |input|
466
520
  Seq.new(
467
- Satisfy.new(IS_LOWER),
468
- Many.new(Satisfy.new(IS_ALPHANUM),"")
469
- ) do |head, tail|
521
+ Satisfy.new(IS_LOWER),
522
+ Many.new(Satisfy.new(IS_ALPHANUM),"")
523
+ ) do |head, tail|
470
524
  head + tail
471
525
  end
472
526
  end
@@ -519,6 +573,14 @@ module Yaparc
519
573
  class AbstractParser
520
574
  include Parsable
521
575
 
576
+ # def parse(input, &block)
577
+ # tree = @parser.call.parse(input)
578
+ # if block_given?
579
+ # yield tree
580
+ # else
581
+ # tree
582
+ # end
583
+ # end
522
584
  def parse(input, &block)
523
585
  tree = @parser.call.parse(input)
524
586
  if block_given?
data/tests/test_parser.rb CHANGED
@@ -186,6 +186,14 @@ class YaparcTest < Test::Unit::TestCase
186
186
  parser = Char.new("a")
187
187
  result = parser.parse("123")
188
188
  assert_instance_of Result::Fail, result
189
+
190
+ parser = Char.new("a", false)
191
+ result = parser.parse("a")
192
+ assert_instance_of Result::OK, result
193
+ result = parser.parse("A")
194
+ assert_instance_of Result::OK, result
195
+ result = parser.parse("!")
196
+ assert_instance_of Result::Fail, result
189
197
  end
190
198
 
191
199
  def test_string_parse
@@ -197,6 +205,12 @@ class YaparcTest < Test::Unit::TestCase
197
205
  parser = Yaparc::String.new("abc")
198
206
  result = parser.parse("ab1234")
199
207
  assert_instance_of Result::Fail, result
208
+
209
+ parser = Yaparc::String.new("abc", false)
210
+ result = parser.parse("abc")
211
+ assert_instance_of Result::OK, result
212
+ result = parser.parse("aBc")
213
+ assert_instance_of Result::OK, result
200
214
  end
201
215
 
202
216
  def test_regex_parse
@@ -211,15 +225,17 @@ class YaparcTest < Test::Unit::TestCase
211
225
  assert_equal "ab", result.input
212
226
 
213
227
  parser = Regex.new(/\A[0-9]+/)
214
- result = parser.parse("1234ab") do |match|
215
- Integer(match)
216
- end
217
- assert_equal 1234, result.value
228
+ result = parser.parse("1234ab")
229
+ # result = parser.parse("1234ab") do |match|
230
+ # Integer(match)
231
+ # end
232
+ # assert_equal 1234, result.value
233
+ assert_equal '1234', result.value
218
234
 
219
- parser = Regex.new(/([0-9]+):([a-z]+)/)
220
- result = parser.parse_with_parameter("1234:ab") do |match1, match2|
221
- assert_equal 'ab', match2
222
- end
235
+ # parser = Regex.new(/([0-9]+):([a-z]+)/)
236
+ # result = parser.parse_with_parameter("1234:ab") do |match1, match2|
237
+ # assert_equal 'ab', match2
238
+ # end
223
239
 
224
240
  parser = Regex.new(/([0-9]+):([a-z]+)/) do |match1, match2|
225
241
  [match2,match1]
@@ -305,19 +321,26 @@ class YaparcTest < Test::Unit::TestCase
305
321
  assert_equal "", result.input
306
322
  end
307
323
 
308
- # def test_space
309
- # parser = Space.new
310
- # result = parser.parse(" abc")
311
- # assert_instance_of Result::OK, result
312
- # assert_equal "abc", result.input
313
- # end
324
+ def test_space
325
+ parser = Space.new
326
+ result = parser.parse(" abc")
327
+ assert_instance_of Result::OK, result
328
+ assert_equal "abc", result.input
329
+ end
314
330
 
315
- # def test_whitespace
316
- # parser = WhiteSpace.new
317
- # result = parser.parse(" \n abc")
318
- # assert_instance_of Result::OK, result
319
- # assert_equal "abc", result.input
320
- # end
331
+ def test_whitespace
332
+ parser = WhiteSpace.new
333
+ result = parser.parse(" \n abc")
334
+ assert_instance_of Result::OK, result
335
+ assert_equal "abc", result.input
336
+ snip =<<-SNIP
337
+
338
+ abc
339
+ SNIP
340
+ result = parser.parse(snip)
341
+ assert_instance_of Result::OK, result
342
+ assert_equal "abc\n", result.input
343
+ end
321
344
 
322
345
  # def test_token
323
346
  # parser = Token.new
@@ -406,6 +429,12 @@ class YaparcTest < Test::Unit::TestCase
406
429
  result = parser.parse(" % ")
407
430
  assert_equal "%", result.value
408
431
  assert_equal "", result.input
432
+
433
+ parser = Literal.new('vgh', false)
434
+ result = parser.parse(" vgh ")
435
+ assert_instance_of Result::OK, result
436
+ result = parser.parse(" vgH ")
437
+ assert_instance_of Result::OK, result
409
438
  end
410
439
  end
411
440
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yaparc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akimichi Tatsukawa
@@ -9,7 +9,7 @@ autorequire: yaparc
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-04-27 00:00:00 +09:00
12
+ date: 2008-05-08 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies: []
15
15