raabro 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +5 -0
- data/README.md +89 -1
- data/lib/raabro.rb +17 -9
- data/spec/sample_xel_spec.rb +9 -14
- metadata +1 -1
data/CHANGELOG.txt
CHANGED
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
|
|
data/lib/raabro.rb
CHANGED
@@ -26,7 +26,7 @@
|
|
26
26
|
|
27
27
|
module Raabro
|
28
28
|
|
29
|
-
VERSION = '1.0.
|
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 &&
|
419
|
+
return rewrite(t) if opts[:rewrite] != false && rewrite(0) == true
|
409
420
|
|
410
421
|
t
|
411
422
|
end
|
412
423
|
|
413
|
-
|
424
|
+
def rewrite(tree)
|
414
425
|
|
415
|
-
|
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
|
-
|
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
|
data/spec/sample_xel_spec.rb
CHANGED
@@ -10,7 +10,7 @@ require 'spec_helper'
|
|
10
10
|
|
11
11
|
module Sample::Xel include Raabro
|
12
12
|
|
13
|
-
#
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
|