yaparc 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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