raabro 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,11 @@
2
2
  = raabro CHANGELOG.txt
3
3
 
4
4
 
5
+ == raabro 1.0.4 released 2015-09-24
6
+
7
+ - provide a default .rewrite implementation
8
+
9
+
5
10
  == raabro 1.0.3 released 2015-09-23
6
11
 
7
12
  - drop the shrink! concept
data/README.md CHANGED
@@ -6,7 +6,95 @@
6
6
 
7
7
  A very dumb PEG parser library.
8
8
 
9
- Son to [aabro](https://github.com/flon-io/aabro), grandson to [neg](https://github.com/jmettraux/neg).
9
+ Son to [aabro](https://github.com/flon-io/aabro), grandson to [neg](https://github.com/jmettraux/neg), grand-grandson to [parslet](https://github.com/kschiess/parslet).
10
+
11
+
12
+ ## a sample parser/rewriter
13
+
14
+ You use raabro by providing the parsing rules, then some rewrite rules.
15
+
16
+ The parsing rules make use of the raabro basic parsers `seq`, `alt`, `str`, `rex`, `eseq`, ...
17
+
18
+ The rewrite rules match names passed as first argument to the basic parsers to rewrite the resulting parse trees.
19
+
20
+ ```ruby
21
+ require 'raabro'
22
+
23
+
24
+ module Fun include Raabro
25
+
26
+ # parse
27
+ #
28
+ # Last function is the root, "i" stands for "input".
29
+
30
+ def pa(i); rex(nil, i, /\(\s*/); end
31
+ def pz(i); rex(nil, i, /\)\s*/); end
32
+ def com(i); rex(nil, i, /,\s*/); end
33
+
34
+ def num(i); rex(:num, i, /-?[0-9]+\s*/); end
35
+
36
+ def args(i); eseq(:args, i, :pa, :exp, :com, :pz); end
37
+ def funame(i); rex(:funame, i, /[a-z][a-z0-9]*/); end
38
+ def fun(i); seq(:fun, i, :funame, :args); end
39
+
40
+ def exp(i); alt(:exp, i, :fun, :num); end
41
+
42
+ # rewrite
43
+ #
44
+ # Names above (:num, :fun, ...) get a rewrite_xxx function.
45
+ # "t" stands for "tree".
46
+
47
+ def rewrite_exp(t); rewrite(t.children[0]); end
48
+ def rewrite_num(t); t.string.to_i; end
49
+
50
+ def rewrite_fun(t)
51
+ [ t.children[0].string ] +
52
+ t.children[1].children.inject([]) { |a, e| a << rewrite(e) if e.name; a }
53
+ end
54
+ end
55
+
56
+
57
+ p Fun.parse('mul(1, 2)')
58
+ # => ["mul", 1, 2]
59
+
60
+ p Fun.parse('mul(1, add(-2, 3))')
61
+ # => ["mul", 1, ["add", -2, 3]]
62
+
63
+ p Fun.parse('mul (1, 2)')
64
+ # => nil (doesn't accept a space after the function name)
65
+ ```
66
+
67
+ This sample is available at: [doc/readme0.rb](doc/readme0.rb).
68
+
69
+
70
+ ## basic parsers
71
+
72
+ The first parameter is the name used by rewrite rules.
73
+ The second parameter is a `Raabro::Input` instance, mostly a wrapped string.
74
+
75
+ ```ruby
76
+ def seq(name, input, *parsers)
77
+ # a sequence of parsers
78
+
79
+ def alt(name, input, *parsers)
80
+ # tries the parsers returns as soon as one succeeds
81
+
82
+ def altg(name, input, *parsers)
83
+ # tries all the parsers, returns with the longest match
84
+
85
+ def rep(name, input, parser, min, max=0)
86
+ # repeats the the wrapped parser
87
+
88
+ def ren(name, input, parser)
89
+ # renames the output of the wrapped parser
90
+
91
+ def jseq(name, input, eltpa, seppa)
92
+ # seq(name, input, eltpa, seppa, eltpa, seppa, eltpaa, seppa, ...)
93
+
94
+ def eseq(name, input, startpa, eltpa, seppa, endpa)
95
+ # seq(name, input, startpa, eltpa, seppa, eltpa, seppa, ..., endpa)
96
+ ```
97
+
10
98
 
11
99
  ## LICENSE
12
100
 
@@ -26,7 +26,7 @@
26
26
 
27
27
  module Raabro
28
28
 
29
- VERSION = '1.0.3'
29
+ VERSION = '1.0.4'
30
30
 
31
31
  class Input
32
32
 
@@ -388,6 +388,17 @@ module Raabro
388
388
  end
389
389
  alias jseq eseq
390
390
 
391
+ attr_accessor :last
392
+
393
+ def method_added(name)
394
+
395
+ m = method(name)
396
+ return unless m.arity == 1
397
+ return unless m.parameters[0][1] == :i || m.parameters[0][1] == :input
398
+
399
+ @last = name.to_sym
400
+ end
401
+
391
402
  def parse(input, opts={})
392
403
 
393
404
  opts[:prune] = true unless opts.has_key?(:prune)
@@ -405,20 +416,17 @@ module Raabro
405
416
 
406
417
  t = t.children.first if t.parter == :all
407
418
 
408
- return rewrite(t) if opts[:rewrite] != false && respond_to?(:rewrite)
419
+ return rewrite(t) if opts[:rewrite] != false && rewrite(0) == true
409
420
 
410
421
  t
411
422
  end
412
423
 
413
- attr_accessor :last
424
+ def rewrite(tree)
414
425
 
415
- def method_added(name)
426
+ return !! methods.find { |m| m.to_s.match(/^rewrite_/) } if tree == 0
427
+ # return true when "rewrite_xxx" methods seem to have been provided
416
428
 
417
- m = method(name)
418
- return unless m.arity == 1
419
- return unless m.parameters[0][1] == :i || m.parameters[0][1] == :input
420
-
421
- @last = name.to_sym
429
+ send("rewrite_#{tree.name}", tree)
422
430
  end
423
431
  end
424
432
  extend ModuleMethods
@@ -10,7 +10,7 @@ require 'spec_helper'
10
10
 
11
11
  module Sample::Xel include Raabro
12
12
 
13
- # parser
13
+ # parse
14
14
 
15
15
  def pa(i); str(nil, i, '('); end
16
16
  def pz(i); str(nil, i, ')'); end
@@ -27,19 +27,14 @@ module Sample::Xel include Raabro
27
27
  #alias root exp
28
28
  # not necessary since Raabro takes the last defined parser as the root
29
29
 
30
- def rewrite(tree)
31
-
32
- case tree.name
33
- when :exp
34
- rewrite tree.children.first
35
- when :num
36
- tree.string.to_i
37
- when :fun
38
- [ tree.children[0].string ] +
39
- tree.children[1].children.select(&:name).collect { |e| rewrite(e) }
40
- else
41
- fail ArgumentError.new("cannot rewrite #{tree.to_a.inspect}")
42
- end
30
+ # rewrite
31
+
32
+ def rewrite_exp(t); rewrite(t.children[0]); end
33
+ def rewrite_num(t); t.string.to_i; end
34
+
35
+ def rewrite_fun(t)
36
+ [ t.children[0].string ] +
37
+ t.children[1].children.inject([]) { |a, e| a << rewrite(e) if e.name; a }
43
38
  end
44
39
  end
45
40
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: raabro
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: