sexpr 0.5.1 → 0.6.0
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.
- data/CHANGELOG.md +16 -0
- data/Gemfile +3 -3
- data/Gemfile.lock +14 -14
- data/Rakefile +0 -4
- data/examples/bool_expr/bool_expr.rb +1 -95
- data/lib/sexpr/grammar/matching.rb +3 -3
- data/lib/sexpr/grammar/parsing.rb +1 -1
- data/lib/sexpr/grammar/tagging.rb +16 -13
- data/lib/sexpr/loader.rb +1 -0
- data/lib/sexpr/matcher.rb +3 -2
- data/lib/sexpr/matcher/many.rb +16 -1
- data/lib/sexpr/matcher/non_terminal.rb +31 -0
- data/lib/sexpr/matcher/rule.rb +3 -6
- data/lib/sexpr/node.rb +1 -1
- data/lib/sexpr/parser.rb +1 -1
- data/lib/sexpr/processor.rb +11 -1
- data/lib/sexpr/processor/helper.rb +1 -1
- data/lib/sexpr/processor/sexpr_coercions.rb +6 -14
- data/lib/sexpr/rewriter.rb +0 -8
- data/lib/sexpr/version.rb +3 -3
- data/sexpr.gemspec +3 -3
- data/sexpr.noespec +13 -6
- data/spec/integration/bool_expr/test_not_push.rb +38 -0
- data/spec/integration/bool_expr/test_parsing.rb +15 -0
- data/spec/integration/bool_expr/test_tagging.rb +25 -0
- data/spec/integration/bool_expr/test_validation.rb +15 -0
- data/spec/{test_readme_examples.rb → integration/test_readme_examples.rb} +0 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/grammar/matching/test_compile_rule.rb +55 -0
- data/spec/{grammar → unit/grammar}/matching/test_compile_rule_defn.rb +0 -0
- data/spec/unit/grammar/matching/test_compile_rules.rb +45 -0
- data/spec/{grammar → unit/grammar}/options/test_install_parser.rb +0 -0
- data/spec/{grammar → unit/grammar}/options/test_install_path.rb +0 -0
- data/spec/{grammar → unit/grammar}/options/test_install_root.rb +0 -0
- data/spec/{grammar → unit/grammar}/tagging/test_looks_a_sexpr.rb +0 -0
- data/spec/{grammar → unit/grammar}/tagging/test_mod2rulename.rb +0 -0
- data/spec/{grammar → unit/grammar}/tagging/test_rule2modname.rb +0 -0
- data/spec/{grammar → unit/grammar}/tagging/test_tag_sexpr.rb +0 -0
- data/spec/unit/grammar/tagging/test_tagging_module_for.rb +72 -0
- data/spec/{grammar → unit/grammar}/test_new.rb +0 -0
- data/spec/{grammar → unit/grammar}/test_parse.rb +0 -0
- data/spec/{grammar → unit/grammar}/test_sexpr.rb +0 -0
- data/spec/{matcher → unit/matcher}/alternative/test_eat.rb +1 -1
- data/spec/{matcher → unit/matcher}/alternative/test_match_q.rb +0 -0
- data/spec/{matcher → unit/matcher}/many/test_eat.rb +0 -0
- data/spec/{matcher → unit/matcher}/many/test_initialize.rb +0 -0
- data/spec/{matcher → unit/matcher}/many/test_match_q.rb +0 -0
- data/spec/unit/matcher/non_terminal/test_eat.rb +31 -0
- data/spec/unit/matcher/non_terminal/test_match_q.rb +32 -0
- data/spec/{matcher → unit/matcher}/reference/test_eat.rb +0 -0
- data/spec/{matcher → unit/matcher}/reference/test_match_q.rb +0 -0
- data/spec/unit/matcher/rule/test_eat.rb +17 -0
- data/spec/unit/matcher/rule/test_match_q.rb +17 -0
- data/spec/{matcher → unit/matcher}/sequence/test_eat.rb +0 -0
- data/spec/{matcher → unit/matcher}/sequence/test_match_q.rb +0 -0
- data/spec/{matcher → unit/matcher}/terminal/test_eat.rb +1 -1
- data/spec/{matcher → unit/matcher}/terminal/test_match_q.rb +0 -0
- data/spec/{matcher → unit/matcher}/terminal/test_terminal_match.rb +0 -0
- data/spec/{node → unit/node}/test_sexpr_body.rb +0 -0
- data/spec/{node → unit/node}/test_sexpr_copy.rb +0 -0
- data/spec/{node → unit/node}/test_sexpr_type.rb +0 -0
- data/spec/{node → unit/node}/test_tracking_markers.rb +0 -0
- data/spec/{parser → unit/parser}/citrus/test_new.rb +0 -0
- data/spec/{parser → unit/parser}/citrus/test_parse.rb +0 -0
- data/spec/{parser → unit/parser}/citrus/test_recognize.rb +0 -0
- data/spec/{parser → unit/parser}/citrus/test_registration.rb +0 -0
- data/spec/{parser → unit/parser}/citrus/test_to_sexpr.rb +0 -0
- data/spec/{parser → unit/parser}/test_factor.rb +0 -0
- data/spec/{parser → unit/parser}/test_input_text.rb +0 -0
- data/spec/{processor → unit/processor}/helper/test_call.rb +0 -0
- data/spec/{processor → unit/processor}/test_apply.rb +0 -0
- data/spec/{processor → unit/processor}/test_build_helper_chain.rb +0 -0
- data/spec/{processor → unit/processor}/test_call.rb +0 -0
- data/spec/unit/processor/test_grammar.rb +56 -0
- data/spec/{processor → unit/processor}/test_helper.rb +0 -0
- data/spec/{processor → unit/processor}/test_sexpr_coercions.rb +6 -2
- data/spec/{processor → unit/processor}/test_use.rb +0 -0
- data/spec/{rewriter → unit/rewriter}/test_copy_and_apply.rb +0 -0
- data/spec/{test_load.rb → unit/test_load.rb} +3 -2
- data/spec/{test_rewriter.rb → unit/test_rewriter.rb} +0 -0
- data/spec/{test_sexpr.rb → unit/test_sexpr.rb} +1 -1
- data/tasks/gem.rake +9 -4
- data/tasks/test.rake +26 -0
- metadata +163 -117
- data/spec/grammar/matching/test_compile_rule.rb +0 -23
- data/spec/matcher/rule/test_eat.rb +0 -21
- data/spec/matcher/rule/test_match_q.rb +0 -24
- data/tasks/spec_test.rake +0 -71
- data/tasks/unit_test.rake +0 -76
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
# 0.6.0 / 2013-09-26
|
|
2
|
+
|
|
3
|
+
* Major enhancements (possibly breaking changes)
|
|
4
|
+
|
|
5
|
+
* All grammar rules are now proper Matcher::Rule instances. A NonTerminal
|
|
6
|
+
matcher is added and is used for non-terminal rule productions and matching
|
|
7
|
+
(all but Terminal and Alternative).
|
|
8
|
+
* `Rewriter.sexpr_grammar` and `Rewriter#sexpr_grammar` have been removed.
|
|
9
|
+
`Processor.grammar` and `Processor#grammar` are provided instead.
|
|
10
|
+
|
|
11
|
+
* Minor enhancements
|
|
12
|
+
|
|
13
|
+
* Added `Grammar#tagging_module_for(rulename)` that returns the user-defined
|
|
14
|
+
module used to tag a given grammar rule production.
|
|
15
|
+
* `Grammar#looks_a_sexpr?(arg)` became public.
|
|
16
|
+
|
|
1
17
|
# 0.5.1 / 2012-03-13
|
|
2
18
|
|
|
3
19
|
* Minor enhancements
|
data/Gemfile
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
source 'http://rubygems.org'
|
|
2
2
|
|
|
3
3
|
group :development do
|
|
4
|
-
gem "
|
|
4
|
+
gem "path", "~> 1.3"
|
|
5
5
|
gem "citrus", "~> 2.4"
|
|
6
|
-
gem "rake", "~> 0
|
|
7
|
-
gem "rspec", "~> 2.
|
|
6
|
+
gem "rake", "~> 10.0"
|
|
7
|
+
gem "rspec", "~> 2.10"
|
|
8
8
|
gem "wlang", "~> 0.10.2"
|
|
9
9
|
end
|
data/Gemfile.lock
CHANGED
|
@@ -2,17 +2,17 @@ GEM
|
|
|
2
2
|
remote: http://rubygems.org/
|
|
3
3
|
specs:
|
|
4
4
|
citrus (2.4.1)
|
|
5
|
-
diff-lcs (1.
|
|
6
|
-
|
|
7
|
-
rake (
|
|
8
|
-
rspec (2.
|
|
9
|
-
rspec-core (~> 2.
|
|
10
|
-
rspec-expectations (~> 2.
|
|
11
|
-
rspec-mocks (~> 2.
|
|
12
|
-
rspec-core (2.
|
|
13
|
-
rspec-expectations (2.
|
|
14
|
-
diff-lcs (
|
|
15
|
-
rspec-mocks (2.
|
|
5
|
+
diff-lcs (1.2.4)
|
|
6
|
+
path (1.3.3)
|
|
7
|
+
rake (10.1.0)
|
|
8
|
+
rspec (2.14.1)
|
|
9
|
+
rspec-core (~> 2.14.0)
|
|
10
|
+
rspec-expectations (~> 2.14.0)
|
|
11
|
+
rspec-mocks (~> 2.14.0)
|
|
12
|
+
rspec-core (2.14.5)
|
|
13
|
+
rspec-expectations (2.14.2)
|
|
14
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
|
15
|
+
rspec-mocks (2.14.3)
|
|
16
16
|
wlang (0.10.2)
|
|
17
17
|
|
|
18
18
|
PLATFORMS
|
|
@@ -21,7 +21,7 @@ PLATFORMS
|
|
|
21
21
|
|
|
22
22
|
DEPENDENCIES
|
|
23
23
|
citrus (~> 2.4)
|
|
24
|
-
|
|
25
|
-
rake (~> 0
|
|
26
|
-
rspec (~> 2.
|
|
24
|
+
path (~> 1.3)
|
|
25
|
+
rake (~> 10.0)
|
|
26
|
+
rspec (~> 2.10)
|
|
27
27
|
wlang (~> 0.10.2)
|
data/Rakefile
CHANGED
|
@@ -56,98 +56,4 @@ module BoolExpr
|
|
|
56
56
|
|
|
57
57
|
end # class NotPushProcessor
|
|
58
58
|
|
|
59
|
-
end # module BoolExpr
|
|
60
|
-
|
|
61
|
-
describe BoolExpr do
|
|
62
|
-
subject{ BoolExpr }
|
|
63
|
-
|
|
64
|
-
describe "the parsing feature" do
|
|
65
|
-
|
|
66
|
-
it 'parses boolean expressions without error' do
|
|
67
|
-
subject.parse("x and y").should be_a(Citrus::Match)
|
|
68
|
-
subject.parse("not(y)").should be_a(Citrus::Match)
|
|
69
|
-
subject.parse("not(true)").should be_a(Citrus::Match)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
it 'provides a shortcut to get s-expressions directly' do
|
|
73
|
-
subject.sexpr("x and y").should eq([:bool_and, [:var_ref, "x"], [:var_ref, "y"]])
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
end # parsing
|
|
77
|
-
|
|
78
|
-
describe "the tagging feature" do
|
|
79
|
-
|
|
80
|
-
it 'tags parsing results with the Sexpr module' do
|
|
81
|
-
sexpr = subject.sexpr("x and y")
|
|
82
|
-
sexpr.should be_a(Sexpr)
|
|
83
|
-
sexpr.sexpr_type.should eq(:bool_and)
|
|
84
|
-
sexpr.sexpr_body.should eq([[:var_ref, "x"], [:var_ref, "y"]])
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
it 'tags parsing results with user modules' do
|
|
88
|
-
subject.sexpr("x and y").should be_a(BoolExpr::And)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
it 'allows tagging manually' do
|
|
92
|
-
subject.sexpr([:bool_lit, true]).should be_a(BoolExpr::Lit)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
it 'applies tagging recursively' do
|
|
96
|
-
sexpr = subject.sexpr([:bool_not, [:bool_lit, true]])
|
|
97
|
-
sexpr.last.should be_a(BoolExpr::Lit)
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
end # taggging
|
|
101
|
-
|
|
102
|
-
describe 'the validation feature' do
|
|
103
|
-
|
|
104
|
-
it 'validates s-expressions' do
|
|
105
|
-
subject.match?([:bool_lit, true]).should be_true
|
|
106
|
-
subject.match?([:bool_lit, "x"]).should be_false
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
it 'validates s-expressions against specific rules' do
|
|
110
|
-
subject[:bool_lit].match?([:bool_lit, true]).should be_true
|
|
111
|
-
subject[:bool_and].match?([:bool_lit, true]).should be_false
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
end # validating
|
|
115
|
-
|
|
116
|
-
describe BoolExpr::NotPushProcessor do
|
|
117
|
-
|
|
118
|
-
def _(expr)
|
|
119
|
-
BoolExpr.sexpr(expr)
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def rw(expr)
|
|
123
|
-
BoolExpr::NotPushProcessor.new.call(expr)
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
it 'does nothing on variable references' do
|
|
127
|
-
rw("not x").should eq([:bool_not, [:var_ref, "x"]])
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
it 'rewrites literals through negating them' do
|
|
131
|
-
rw("not true").should eq(_ "false")
|
|
132
|
-
rw("not false").should eq(_ "true")
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
it 'rewrites not through removing them' do
|
|
136
|
-
rw("not not true").should eq(_ "true")
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
it 'rewrites or through and of negated terms' do
|
|
140
|
-
rw("not(x or y)").should eq(_ "not(x) and not(y)")
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
it 'rewrites and through or of negated terms' do
|
|
144
|
-
rw("not(x and y)").should eq(_ "not(x) or not(y)")
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
it 'rewrites recursively' do
|
|
148
|
-
rw("not(x and not(y))").should eq(_ "not(x) or y")
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
end # rewriting
|
|
152
|
-
|
|
153
|
-
end if defined?(RSpec)
|
|
59
|
+
end # module BoolExpr
|
|
@@ -15,7 +15,7 @@ module Sexpr
|
|
|
15
15
|
end
|
|
16
16
|
alias :=== :match?
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
private
|
|
19
19
|
|
|
20
20
|
def compile_rules(rules)
|
|
21
21
|
Hash[rules.map{|k,v|
|
|
@@ -26,10 +26,10 @@ module Sexpr
|
|
|
26
26
|
def compile_rule(name, defn)
|
|
27
27
|
case rule = compile_rule_defn(defn)
|
|
28
28
|
when Matcher::Terminal, Matcher::Alternative
|
|
29
|
-
rule
|
|
30
29
|
else
|
|
31
|
-
Matcher::
|
|
30
|
+
rule = Matcher::NonTerminal.new(name, rule)
|
|
32
31
|
end
|
|
32
|
+
Matcher::Rule.new(name, rule)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def compile_rule_defn(arg, grammar = self)
|
|
@@ -19,6 +19,15 @@ module Sexpr
|
|
|
19
19
|
nil
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
def tagging_module_for(rulename)
|
|
23
|
+
if ref = tagging_reference
|
|
24
|
+
modname = rule2modname(rulename)
|
|
25
|
+
ref.const_get(modname, false) rescue default_tagging_module
|
|
26
|
+
else
|
|
27
|
+
default_tagging_module
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
22
31
|
def sexpr(input, markers = nil)
|
|
23
32
|
case input
|
|
24
33
|
when Array
|
|
@@ -29,7 +38,11 @@ module Sexpr
|
|
|
29
38
|
end
|
|
30
39
|
end
|
|
31
40
|
|
|
32
|
-
|
|
41
|
+
def looks_a_sexpr?(arg)
|
|
42
|
+
arg.is_a?(Array) and arg.first.is_a?(Symbol)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
33
46
|
|
|
34
47
|
def tag_sexpr(sexpr, markers = nil, force = false)
|
|
35
48
|
return sexpr unless looks_a_sexpr?(sexpr)
|
|
@@ -53,21 +66,11 @@ module Sexpr
|
|
|
53
66
|
end
|
|
54
67
|
|
|
55
68
|
def tag_sexpr_with_user_module(sexpr)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
modname = rule2modname(rulename)
|
|
59
|
-
tag = ref.const_get(modname, false) rescue default_tagging_module
|
|
60
|
-
sexpr.extend(tag) if tag
|
|
61
|
-
elsif tag = default_tagging_module
|
|
62
|
-
sexpr.extend(tag)
|
|
63
|
-
end
|
|
69
|
+
tag = tagging_module_for(sexpr.first)
|
|
70
|
+
sexpr.extend(tag) if tag
|
|
64
71
|
sexpr
|
|
65
72
|
end
|
|
66
73
|
|
|
67
|
-
def looks_a_sexpr?(arg)
|
|
68
|
-
arg.is_a?(Array) and arg.first.is_a?(Symbol)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
74
|
def parser!
|
|
72
75
|
raise NoParserError, "No parser set.", caller
|
|
73
76
|
end
|
data/lib/sexpr/loader.rb
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
data/lib/sexpr/matcher.rb
CHANGED
|
@@ -10,6 +10,7 @@ end # module Sexpr
|
|
|
10
10
|
require_relative "matcher/alternative"
|
|
11
11
|
require_relative "matcher/many"
|
|
12
12
|
require_relative "matcher/reference"
|
|
13
|
-
require_relative "matcher/rule"
|
|
14
13
|
require_relative "matcher/sequence"
|
|
15
|
-
require_relative "matcher/terminal"
|
|
14
|
+
require_relative "matcher/terminal"
|
|
15
|
+
require_relative "matcher/non_terminal"
|
|
16
|
+
require_relative "matcher/rule"
|
data/lib/sexpr/matcher/many.rb
CHANGED
|
@@ -28,11 +28,26 @@ module Sexpr
|
|
|
28
28
|
i >= @min ? last : nil
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
def parse(sexp, to = [])
|
|
32
|
+
i, last, got = 0, sexp, []
|
|
33
|
+
while sexp && (@max.nil? || i < @max)
|
|
34
|
+
if res = @term.parse(sexp, got)
|
|
35
|
+
last = res
|
|
36
|
+
i += 1
|
|
37
|
+
end
|
|
38
|
+
sexp = res
|
|
39
|
+
end
|
|
40
|
+
if i >= @min
|
|
41
|
+
got.each{|x| to << x }
|
|
42
|
+
last
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
31
46
|
def inspect
|
|
32
47
|
"(many #{term.inspect}, #{min}, #{max})"
|
|
33
48
|
end
|
|
34
49
|
|
|
35
|
-
|
|
50
|
+
private
|
|
36
51
|
|
|
37
52
|
def minmax(min, max)
|
|
38
53
|
case min
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Sexpr
|
|
2
|
+
module Matcher
|
|
3
|
+
class NonTerminal
|
|
4
|
+
include Matcher
|
|
5
|
+
|
|
6
|
+
attr_reader :name
|
|
7
|
+
attr_reader :defn
|
|
8
|
+
|
|
9
|
+
def initialize(name, defn)
|
|
10
|
+
@name = name
|
|
11
|
+
@defn = defn
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def match?(sexp)
|
|
15
|
+
return nil unless sexp.is_a?(Array)
|
|
16
|
+
return false unless sexp.first && (sexp.first == name)
|
|
17
|
+
defn.match?(sexp[1..-1])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def eat(sexp)
|
|
21
|
+
return nil unless match?(sexp.first)
|
|
22
|
+
sexp[1..-1]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def inspect
|
|
26
|
+
"(non-terminal #{name}, #{defn.inspect})"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end # class NonTerminal
|
|
30
|
+
end # module Matcher
|
|
31
|
+
end # module Sexpr
|
data/lib/sexpr/matcher/rule.rb
CHANGED
|
@@ -12,14 +12,11 @@ module Sexpr
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def match?(sexp)
|
|
15
|
-
|
|
16
|
-
return false unless sexp.first && (sexp.first == name)
|
|
17
|
-
defn.match?(sexp[1..-1])
|
|
15
|
+
defn.match?(sexp)
|
|
18
16
|
end
|
|
19
17
|
|
|
20
18
|
def eat(sexp)
|
|
21
|
-
|
|
22
|
-
sexp[1..-1]
|
|
19
|
+
defn.eat(sexp)
|
|
23
20
|
end
|
|
24
21
|
|
|
25
22
|
def inspect
|
|
@@ -28,4 +25,4 @@ module Sexpr
|
|
|
28
25
|
|
|
29
26
|
end # class Rule
|
|
30
27
|
end # module Matcher
|
|
31
|
-
end # module Sexpr
|
|
28
|
+
end # module Sexpr
|
data/lib/sexpr/node.rb
CHANGED
data/lib/sexpr/parser.rb
CHANGED
data/lib/sexpr/processor.rb
CHANGED
|
@@ -6,6 +6,12 @@ module Sexpr
|
|
|
6
6
|
|
|
7
7
|
class << self
|
|
8
8
|
|
|
9
|
+
def grammar(grammar = nil)
|
|
10
|
+
@grammar = grammar if grammar
|
|
11
|
+
@grammar ||= (@grammar || superclass.grammar) rescue Sexpr
|
|
12
|
+
@grammar
|
|
13
|
+
end
|
|
14
|
+
|
|
9
15
|
def preprocessors
|
|
10
16
|
@preprocessors ||= superclass.preprocessors.dup rescue [ ]
|
|
11
17
|
end
|
|
@@ -46,6 +52,10 @@ module Sexpr
|
|
|
46
52
|
@options = options || {}
|
|
47
53
|
end
|
|
48
54
|
|
|
55
|
+
def grammar
|
|
56
|
+
self.class.grammar
|
|
57
|
+
end
|
|
58
|
+
|
|
49
59
|
def call(sexpr)
|
|
50
60
|
apply(preprocess(sexpr))
|
|
51
61
|
end
|
|
@@ -62,7 +72,7 @@ module Sexpr
|
|
|
62
72
|
raise UnexpectedSexprError, "Unexpected sexpr: #{sexpr.inspect}"
|
|
63
73
|
end
|
|
64
74
|
|
|
65
|
-
|
|
75
|
+
private
|
|
66
76
|
|
|
67
77
|
def preprocess(sexpr)
|
|
68
78
|
preprocessors = self.class.preprocessors
|
|
@@ -5,40 +5,32 @@ module Sexpr
|
|
|
5
5
|
module Methods
|
|
6
6
|
|
|
7
7
|
def parse(*args)
|
|
8
|
-
|
|
8
|
+
grammar.parse(*args)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def sexpr(*args)
|
|
12
|
-
|
|
12
|
+
grammar.sexpr(*args)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def call(processor, sexpr, &bl)
|
|
18
|
+
g = processor.class.grammar
|
|
19
|
+
|
|
18
20
|
# input coercion
|
|
19
|
-
sexpr =
|
|
21
|
+
sexpr = g.sexpr(sexpr)
|
|
20
22
|
|
|
21
23
|
# recursive call
|
|
22
24
|
sexpr = next_call(processor, sexpr, bl)
|
|
23
25
|
|
|
24
26
|
# output coercion
|
|
25
27
|
if sexpr.is_a?(Array) and sexpr.first.is_a?(Symbol)
|
|
26
|
-
|
|
28
|
+
g.sexpr(sexpr)
|
|
27
29
|
else
|
|
28
30
|
sexpr
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
33
|
|
|
32
|
-
private
|
|
33
|
-
|
|
34
|
-
def grammar(processor)
|
|
35
|
-
if processor.respond_to?(:sexpr_grammar)
|
|
36
|
-
processor.sexpr_grammar
|
|
37
|
-
else
|
|
38
|
-
Sexpr
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
34
|
end # class SexprCoercions
|
|
43
35
|
end # class Processor
|
|
44
36
|
end # module Sexpr
|