sexpr 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +56 -17
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +3 -0
- data/Rakefile +0 -8
- data/examples/bool_expr/bool_expr.rb +3 -3
- data/lib/sexpr/grammar/tagging.rb +19 -10
- data/lib/sexpr/processor.rb +58 -20
- data/lib/sexpr/rewriter.rb +1 -1
- data/lib/sexpr/version.rb +1 -1
- data/sexpr.gemspec +1 -1
- data/sexpr.noespec +3 -3
- data/spec/fixtures/bar.rb +9 -0
- data/spec/fixtures/foo.rb +14 -0
- data/spec/fixtures/preprocessed.rb +33 -0
- data/spec/fixtures/simple_processor.rb +19 -0
- data/spec/grammar/tagging/test_tag_sexpr.rb +32 -7
- data/spec/processor/test_apply.rb +34 -0
- data/spec/processor/test_call.rb +30 -29
- data/spec/processor/test_use.rb +22 -0
- data/spec/spec_helper.rb +1 -21
- metadata +25 -18
- data/spec/processor/test_main_processor.rb +0 -18
data/CHANGELOG.md
CHANGED
@@ -1,14 +1,53 @@
|
|
1
|
+
# 0.5.0 / 2012-02-25
|
2
|
+
|
3
|
+
* Major enhancements
|
4
|
+
|
5
|
+
* `Processor#apply` is introduced and is intended to be used to apply processing rules
|
6
|
+
from the inside of the processor class. This method is equivalent to `#call` when no
|
7
|
+
preprocessor is installed (see below).
|
8
|
+
* Preprocessors can now be installed on a Processor through its `use` class method.
|
9
|
+
Preprocessors are applied ala 'Enumerable#inject' on the s-expression passed at
|
10
|
+
`Prcoessor#call`. The preprocessed result is then passed to `#apply` for further
|
11
|
+
processing by the processor itself.
|
12
|
+
(Please note that preprocessing is *not* performed by `#apply` itself; preprocessing
|
13
|
+
is typically applied once one the whole abstract syntax tree instead of successively
|
14
|
+
when its nodes are encountered. Tip: use helpers for such behavior).
|
15
|
+
* `Processor.use` can also be used to make specific computations ahead of processing
|
16
|
+
(such as a symbol table). For this, simply pass a Hash that maps a computation name
|
17
|
+
to a processor class. Attribute readers are automatically installed on the processor
|
18
|
+
class and instance variables set by `#call` accordingly.
|
19
|
+
(Please note such preprocessors do not participate to the rewriting chain described
|
20
|
+
above.)
|
21
|
+
|
22
|
+
* Minor enhancements
|
23
|
+
|
24
|
+
* `Processor.call(sexpr, opts)` is a shortcut for `Processor.new(opts).call(sexpr)`
|
25
|
+
* `Grammar#default_taggging_module` is introduced for cases where either no fine-grained
|
26
|
+
tagging is needed (e.g. all nodes tagged with the same Node module) or fine-grained
|
27
|
+
tagging is needed but is not a total function (e.g. not all nodes have a
|
28
|
+
specialization of Node).
|
29
|
+
|
30
|
+
* Bug fixes
|
31
|
+
|
32
|
+
* Processor options taken at construction are now correctly kept under @options (an
|
33
|
+
attribute reader is provided)
|
34
|
+
|
35
|
+
* Breaking changes
|
36
|
+
|
37
|
+
* The `Processor#main_processor` feature (undocumented and unused in examples) has been
|
38
|
+
removed. Using preprocessors is much cleaner that linking processors to each other.
|
39
|
+
|
1
40
|
# 0.4.0 / 2012-02-23
|
2
41
|
|
3
42
|
* Major enhancements
|
4
43
|
|
5
|
-
* A processing/rewriting framework has been added to Sexpr. See the `Processor` and
|
6
|
-
classes, as well as the boolean expression example.
|
7
|
-
* Tracking markers can now decorate s-expressions, provided they include the `Sexpr`
|
8
|
-
Tracking markers are a simple Hash of meta-information (i.e. not taken into
|
9
|
-
equality for s-expressions). Such markers can be set with
|
10
|
-
Default markers are typically provided by parsers for
|
11
|
-
with the source text it comes from.
|
44
|
+
* A processing/rewriting framework has been added to Sexpr. See the `Processor` and
|
45
|
+
`Rewriter` classes, as well as the boolean expression example.
|
46
|
+
* Tracking markers can now decorate s-expressions, provided they include the `Sexpr`
|
47
|
+
module. Tracking markers are a simple Hash of meta-information (i.e. not taken into
|
48
|
+
account for equality for s-expressions). Such markers can be set with
|
49
|
+
`Grammar#sexpr(sexpr, markers)`. Default markers are typically provided by parsers for
|
50
|
+
traceability of the s-expression with the source text it comes from.
|
12
51
|
|
13
52
|
* Minor enhancements
|
14
53
|
|
@@ -20,12 +59,12 @@
|
|
20
59
|
|
21
60
|
* Breaking changes
|
22
61
|
|
23
|
-
* `Parser.factor` does no longer accept options. This is to avoid the 'yet another
|
24
|
-
symptom and favor convention over configuration.
|
62
|
+
* `Parser.factor` does no longer accept options. This is to avoid the 'yet another
|
63
|
+
options' symptom and favor convention over configuration.
|
25
64
|
* Accordingly, `Sexpr::Citrus::Parser` no longer takes options at construction either.
|
26
|
-
* `Grammar#sexpr` does no longer allow parsing options as second argument, but takes
|
27
|
-
markers (see enhancements). To palliate to this, default parsing options can
|
28
|
-
specified through `Grammar#default_parse_options` (see enhancements).
|
65
|
+
* `Grammar#sexpr` does no longer allow parsing options as second argument, but takes
|
66
|
+
tracking markers (see enhancements). To palliate to this, default parsing options can
|
67
|
+
now be specified through `Grammar#default_parse_options` (see enhancements).
|
29
68
|
|
30
69
|
# 0.3.0 / 2012-02-21
|
31
70
|
|
@@ -44,11 +83,11 @@
|
|
44
83
|
the result to a constant makes perfect sense and benefits from the ruby's magic naming
|
45
84
|
feature.
|
46
85
|
* A loaded grammar now respond to a :sexpr method that parses (if needed) and returns a
|
47
|
-
s-expression. The latter, and all its sub-expressions are automatically tagged with
|
48
|
-
Sexpr module, as well as with user-defined modules. The latter are automatically
|
49
|
-
with a convention over configuration heuristics that associates rule names
|
50
|
-
That convention may however be overridden with specific grammar
|
51
|
-
example).
|
86
|
+
s-expression. The latter, and all its sub-expressions are automatically tagged with
|
87
|
+
the Sexpr module, as well as with user-defined modules. The latter are automatically
|
88
|
+
discovered with a convention over configuration heuristics that associates rule names
|
89
|
+
to module names. That convention may however be overridden with specific grammar
|
90
|
+
methods (see the BoolExpr example).
|
52
91
|
|
53
92
|
# 0.2.0 / 2012-02-21
|
54
93
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Sexpr
|
2
2
|
|
3
|
+
[![Build Status](https://secure.travis-ci.org/blambeau/sexpr.png)](http://travis-ci.org/blambeau/sexpr)
|
4
|
+
[![Dependency Status](https://gemnasium.com/blambeau/sexpr.png)](https://gemnasium.com/blambeau/sexpr)
|
5
|
+
|
3
6
|
A ruby compilation framework around s-expressions.
|
4
7
|
|
5
8
|
## Links
|
data/Rakefile
CHANGED
@@ -1,11 +1,3 @@
|
|
1
|
-
begin
|
2
|
-
gem "bundler", "~> 1.0"
|
3
|
-
require "bundler/setup"
|
4
|
-
rescue LoadError => ex
|
5
|
-
puts ex.message
|
6
|
-
abort "Bundler failed to load, (did you run 'gem install bundler' ?)"
|
7
|
-
end
|
8
|
-
|
9
1
|
# Dynamically load the gem spec
|
10
2
|
$gemspec_file = File.expand_path('../sexpr.gemspec', __FILE__)
|
11
3
|
$gemspec = Kernel.eval(File.read($gemspec_file))
|
@@ -42,9 +42,9 @@ module BoolExpr
|
|
42
42
|
# cases
|
43
43
|
def on_bool_not(sexpr)
|
44
44
|
case expr = sexpr.last
|
45
|
-
when And then
|
46
|
-
when Or then
|
47
|
-
when Not then
|
45
|
+
when And then apply [:bool_or, [:bool_not, expr[1]], [:bool_not, expr[2]] ]
|
46
|
+
when Or then apply [:bool_and, [:bool_not, expr[1]], [:bool_not, expr[2]] ]
|
47
|
+
when Not then apply expr.last
|
48
48
|
when Lit then [:bool_lit, !expr.last]
|
49
49
|
else
|
50
50
|
sexpr
|
@@ -15,25 +15,29 @@ module Sexpr
|
|
15
15
|
nil
|
16
16
|
end
|
17
17
|
|
18
|
+
def default_tagging_module
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
18
22
|
def sexpr(input, markers = nil)
|
19
23
|
case input
|
20
24
|
when Array
|
21
|
-
tag_sexpr input,
|
25
|
+
tag_sexpr input, markers
|
22
26
|
else
|
23
27
|
sexpr = parser!.to_sexpr(parse(input))
|
24
|
-
tag_sexpr sexpr,
|
28
|
+
tag_sexpr sexpr, markers, true
|
25
29
|
end
|
26
30
|
end
|
27
31
|
|
28
32
|
private
|
29
33
|
|
30
|
-
def tag_sexpr(sexpr,
|
34
|
+
def tag_sexpr(sexpr, markers = nil, force = false)
|
31
35
|
return sexpr unless looks_a_sexpr?(sexpr)
|
32
36
|
return sexpr if Sexpr===sexpr and not(force) and markers.nil?
|
33
37
|
|
34
38
|
# set the Sexpr modules
|
35
39
|
sexpr.extend(Sexpr) unless Sexpr===sexpr
|
36
|
-
tag_sexpr_with_user_module(sexpr
|
40
|
+
tag_sexpr_with_user_module(sexpr)
|
37
41
|
|
38
42
|
# set the markers if any
|
39
43
|
if markers
|
@@ -43,16 +47,21 @@ module Sexpr
|
|
43
47
|
|
44
48
|
# recurse
|
45
49
|
sexpr[1..-1].each do |child|
|
46
|
-
tag_sexpr(child,
|
50
|
+
tag_sexpr(child, nil, force)
|
47
51
|
end
|
48
52
|
sexpr
|
49
53
|
end
|
50
54
|
|
51
|
-
def tag_sexpr_with_user_module(sexpr
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
def tag_sexpr_with_user_module(sexpr)
|
56
|
+
if ref = tagging_reference
|
57
|
+
rulename = sexpr.first
|
58
|
+
modname = rule2modname(rulename)
|
59
|
+
tag = ref.const_get(modname) rescue default_tagging_module
|
60
|
+
sexpr.extend(tag) if tag
|
61
|
+
elsif tag = default_tagging_module
|
62
|
+
sexpr.extend(tag)
|
63
|
+
end
|
64
|
+
sexpr
|
56
65
|
end
|
57
66
|
|
58
67
|
def looks_a_sexpr?(arg)
|
data/lib/sexpr/processor.rb
CHANGED
@@ -4,36 +4,53 @@ require_relative 'processor/sexpr_coercions'
|
|
4
4
|
module Sexpr
|
5
5
|
class Processor
|
6
6
|
|
7
|
-
|
7
|
+
class << self
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
def preprocessors
|
10
|
+
@preprocessors ||= superclass.preprocessors.dup rescue [ ]
|
11
|
+
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
13
|
+
def use(preprocessor, options = nil)
|
14
|
+
preprocessor.keys.each{|k| attr_reader(k)} if preprocessor.is_a?(Hash)
|
15
|
+
preprocessors << [preprocessor, options]
|
16
|
+
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
helpers[0...-1].reverse.inject(helpers.last.new) do |chain, h_class|
|
22
|
-
prepended = h_class.new
|
23
|
-
prepended.next_in_chain = chain
|
24
|
-
prepended
|
18
|
+
def helpers
|
19
|
+
@helpers ||= superclass.helpers.dup rescue [ ]
|
25
20
|
end
|
26
|
-
end
|
27
21
|
|
28
|
-
|
22
|
+
def helper(helper_class)
|
23
|
+
methods = helper_class.const_get(:Methods) rescue nil
|
24
|
+
module_eval{ include methods } if methods
|
25
|
+
helpers << helper_class
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_helper_chain(helpers = self.helpers)
|
29
|
+
return NullHelper.new if helpers.empty?
|
30
|
+
helpers[0...-1].reverse.inject(helpers.last.new) do |chain, h_class|
|
31
|
+
prepended = h_class.new
|
32
|
+
prepended.next_in_chain = chain
|
33
|
+
prepended
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(sexpr, options = nil)
|
38
|
+
new(options).call(sexpr)
|
39
|
+
end
|
29
40
|
|
30
|
-
|
41
|
+
end # class << self
|
31
42
|
|
32
|
-
|
33
|
-
|
43
|
+
attr_reader :options
|
44
|
+
|
45
|
+
def initialize(options = nil)
|
46
|
+
@options = options || {}
|
34
47
|
end
|
35
48
|
|
36
49
|
def call(sexpr)
|
50
|
+
apply(preprocess(sexpr))
|
51
|
+
end
|
52
|
+
|
53
|
+
def apply(sexpr)
|
37
54
|
help(sexpr) do |n|
|
38
55
|
meth = :"on_#{n.first}"
|
39
56
|
meth = :"on_missing" unless respond_to?(meth)
|
@@ -47,6 +64,27 @@ module Sexpr
|
|
47
64
|
|
48
65
|
private
|
49
66
|
|
67
|
+
def preprocess(sexpr)
|
68
|
+
preprocessors = self.class.preprocessors
|
69
|
+
preprocessors.each do |pre|
|
70
|
+
sexpr = _preprocess(sexpr, pre)
|
71
|
+
end
|
72
|
+
sexpr
|
73
|
+
end
|
74
|
+
|
75
|
+
def _preprocess(sexpr, preprocessing)
|
76
|
+
pre_class, options = preprocessing
|
77
|
+
if Hash===pre_class
|
78
|
+
pre_class.each_pair do |k,v|
|
79
|
+
computed = v.new(options).call(sexpr)
|
80
|
+
self.instance_variable_set(:"@#{k}", computed)
|
81
|
+
end
|
82
|
+
sexpr
|
83
|
+
else
|
84
|
+
pre_class.new(options).call(sexpr)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
50
88
|
def helper_chain
|
51
89
|
@helper_chain ||= self.class.build_helper_chain
|
52
90
|
end
|
data/lib/sexpr/rewriter.rb
CHANGED
data/lib/sexpr/version.rb
CHANGED
data/sexpr.gemspec
CHANGED
@@ -126,7 +126,7 @@ Gem::Specification.new do |s|
|
|
126
126
|
s.add_development_dependency("epath", "~> 0.0.1")
|
127
127
|
s.add_development_dependency("citrus", "~> 2.4")
|
128
128
|
s.add_development_dependency("rake", "~> 0.9.2")
|
129
|
-
s.add_development_dependency("rspec", "~> 2.8
|
129
|
+
s.add_development_dependency("rspec", "~> 2.8")
|
130
130
|
s.add_development_dependency("wlang", "~> 0.10.2")
|
131
131
|
|
132
132
|
|
data/sexpr.noespec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
template-info:
|
2
2
|
name: "ruby"
|
3
|
-
version: 1.7.
|
3
|
+
version: 1.7.3
|
4
4
|
links:
|
5
5
|
source: https://github.com/blambeau/noe
|
6
6
|
variables:
|
@@ -9,7 +9,7 @@ variables:
|
|
9
9
|
upper:
|
10
10
|
Sexpr
|
11
11
|
version:
|
12
|
-
0.
|
12
|
+
0.5.0
|
13
13
|
summary: |-
|
14
14
|
A compilation framework around s-expressions
|
15
15
|
description: |-
|
@@ -22,5 +22,5 @@ variables:
|
|
22
22
|
- {name: epath, version: "~> 0.0.1", groups: [development]}
|
23
23
|
- {name: citrus, version: "~> 2.4", groups: [development]}
|
24
24
|
- {name: rake, version: "~> 0.9.2", groups: [development]}
|
25
|
-
- {name: rspec, version: "~> 2.8
|
25
|
+
- {name: rspec, version: "~> 2.8", groups: [development]}
|
26
26
|
- {name: wlang, version: "~> 0.10.2", groups: [development]}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Preprocessed < Sexpr::Processor
|
2
|
+
|
3
|
+
class Prefix < Sexpr::Processor
|
4
|
+
|
5
|
+
def on_missing(sexpr)
|
6
|
+
[ :"#{options[:prefix]}#{sexpr.first}" ] + sexpr[1..-1]
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
use Prefix, :prefix => "prefix_"
|
11
|
+
|
12
|
+
def on_prefix_hello(sexpr)
|
13
|
+
[:preprocessed_hello, sexpr]
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_apply(sexpr)
|
17
|
+
apply(sexpr.last)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class SubPreprocessed < Preprocessed
|
23
|
+
|
24
|
+
class Upcase < Sexpr::Processor
|
25
|
+
|
26
|
+
def call(sexpr)
|
27
|
+
sexpr.first.to_s.upcase
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
use :upcased => Upcase
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class SimpleProcessor < Sexpr::Processor
|
2
|
+
|
3
|
+
def on_hello(sexpr)
|
4
|
+
[:simple_hello, sexpr]
|
5
|
+
end
|
6
|
+
|
7
|
+
def on_missing(sexpr)
|
8
|
+
if sexpr.first == :simple_missing
|
9
|
+
[:simple_pass_missing, sexpr]
|
10
|
+
else
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_apply(sexpr)
|
16
|
+
apply(sexpr.last)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -4,24 +4,49 @@ module Sexpr::Grammar
|
|
4
4
|
include Tagging
|
5
5
|
|
6
6
|
module TaggingReference
|
7
|
+
module Node; end
|
7
8
|
module Not; end
|
8
9
|
module Lit; end
|
9
10
|
end
|
10
11
|
|
12
|
+
def default_tagging_module
|
13
|
+
TaggingReference::Node
|
14
|
+
end
|
15
|
+
|
11
16
|
def tag(x)
|
12
|
-
res = tag_sexpr(x
|
17
|
+
res = tag_sexpr(x)
|
13
18
|
res.should eq(x)
|
14
19
|
res
|
15
20
|
end
|
16
21
|
|
17
|
-
|
18
|
-
|
22
|
+
context 'when no tagging reference is provided' do
|
23
|
+
|
24
|
+
it 'tags with the default tagging module if set' do
|
25
|
+
tag([:lit]).should be_a(TaggingReference::Node)
|
26
|
+
tag([:or]).should be_a(TaggingReference::Node)
|
27
|
+
end
|
28
|
+
|
19
29
|
end
|
20
30
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
31
|
+
context 'when a tagging reference is provided' do
|
32
|
+
|
33
|
+
def tagging_reference
|
34
|
+
TaggingReference
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'tags a sexpr at first level' do
|
38
|
+
tag([:lit]).should be_a(TaggingReference::Lit)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'tags sexpr recursively' do
|
42
|
+
res = tag([:not, [:lit, true]])
|
43
|
+
res.should be_a(TaggingReference::Not)
|
44
|
+
res.last.should be_a(TaggingReference::Lit)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'tags with the default tagging module when no match' do
|
48
|
+
res = tag([:or]).should be_a(TaggingReference::Node)
|
49
|
+
end
|
25
50
|
end
|
26
51
|
|
27
52
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Sexpr
|
3
|
+
describe Processor, 'apply' do
|
4
|
+
|
5
|
+
let(:proc){ SimpleProcessor.new }
|
6
|
+
|
7
|
+
it 'dispatches to existing methods' do
|
8
|
+
ast = [:hello, "world"]
|
9
|
+
proc.apply(ast).should eq([:simple_hello, [:hello, "world"]])
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'calls on_missing when not found' do
|
13
|
+
ast = [:simple_missing, [:hello, "world"]]
|
14
|
+
proc.apply(ast).should eq([:simple_pass_missing, ast])
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'can be called from the inside' do
|
18
|
+
ast = [:apply, [:hello, "world"]]
|
19
|
+
proc.apply(ast).should eq([:simple_hello, [:hello, "world"]])
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'raises unexpected by default in on_missing' do
|
23
|
+
ast = [:nonono, "world"]
|
24
|
+
lambda{ proc.apply(ast) }.should raise_error(UnexpectedSexprError, /nonono/)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'raises an ArgumentError unless called on a sexpr' do
|
28
|
+
lambda{
|
29
|
+
proc.apply("world").should raise_error(ArgumentError, /world/)
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/spec/processor/test_call.rb
CHANGED
@@ -2,44 +2,45 @@ require 'spec_helper'
|
|
2
2
|
module Sexpr
|
3
3
|
describe Processor, 'call' do
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
context 'without preprocessors installed' do
|
6
|
+
let(:proc){ SimpleProcessor.new }
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
it 'returns the result of apply' do
|
9
|
+
ast = [:hello, "world"]
|
10
|
+
proc.call(ast).should eq([:simple_hello, [:hello, "world"]])
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
[:seen_missing, sexpr]
|
15
|
-
else
|
16
|
-
super
|
17
|
-
end
|
18
|
-
end
|
15
|
+
context "when preprocessors are installed" do
|
16
|
+
let(:proc){ SubPreprocessed.new }
|
19
17
|
|
18
|
+
it 'applies the preprocessors' do
|
19
|
+
ast = [:hello, "world"]
|
20
|
+
proc.call(ast).should eq([:preprocessed_hello, [:prefix_hello, "world"]])
|
20
21
|
end
|
21
|
-
}
|
22
|
-
let(:proc){ procclass.new }
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
it 'sets preprocessor results under state variables when required' do
|
24
|
+
ast = [:hello, "world"]
|
25
|
+
proc.call(ast)
|
26
|
+
proc.upcased.should eq("PREFIX_HELLO")
|
27
|
+
end
|
28
28
|
|
29
|
-
it 'calls on_missing when not found' do
|
30
|
-
ast = [:nosuchone, "world"]
|
31
|
-
proc.call(ast).should eq([:seen_missing, [:nosuchone, "world"]])
|
32
29
|
end
|
33
30
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
context 'when called on the class' do
|
32
|
+
|
33
|
+
it 'returns what an instance returns' do
|
34
|
+
expected = [:simple_hello, [:hello, "world"]]
|
35
|
+
SimpleProcessor.call([:hello, "world"]).should eq(expected)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'allows passing options' do
|
39
|
+
source = [:hello, "world"]
|
40
|
+
expected = [:do_hello, "world"]
|
41
|
+
Preprocessed::Prefix.call(source, :prefix => "do_").should eq(expected)
|
42
|
+
end
|
38
43
|
|
39
|
-
it 'raises an ArgumentError unless called on a sexpr' do
|
40
|
-
lambda{
|
41
|
-
proc.call("world").should raise_error(ArgumentError, /world/)
|
42
|
-
}
|
43
44
|
end
|
44
45
|
|
45
46
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Sexpr
|
3
|
+
describe Processor, "use" do
|
4
|
+
|
5
|
+
it 'installs the preprocessors properly' do
|
6
|
+
expected = []
|
7
|
+
Processor.preprocessors.should eq(expected)
|
8
|
+
|
9
|
+
expected << [Preprocessed::Prefix, {:prefix => "prefix_"}]
|
10
|
+
Preprocessed.preprocessors.should eq(expected)
|
11
|
+
|
12
|
+
expected << [ {:upcased => SubPreprocessed::Upcase}, nil ]
|
13
|
+
SubPreprocessed.preprocessors.should eq(expected)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'sets attribute readers for hashes' do
|
17
|
+
Preprocessed.new.should_not respond_to(:upcased)
|
18
|
+
SubPreprocessed.new.should respond_to(:upcased)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,27 +7,7 @@ $LOAD_PATH.unshift (root/"lib").to_s
|
|
7
7
|
require 'sexpr'
|
8
8
|
require (root/"examples/bool_expr/bool_expr").to_s
|
9
9
|
|
10
|
-
|
11
|
-
module Methods
|
12
|
-
end
|
13
|
-
|
14
|
-
def on_hello(rw, node)
|
15
|
-
raise unless rw.is_a?(FooProcessor)
|
16
|
-
[:foo_hello, yield(rw, node)]
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
class FooProcessor < Sexpr::Processor
|
21
|
-
helper FooHelper
|
22
|
-
end
|
23
|
-
|
24
|
-
class BarHelper < Sexpr::Processor::Helper
|
25
|
-
module Methods
|
26
|
-
end
|
27
|
-
end
|
28
|
-
class BarProcessor < FooProcessor
|
29
|
-
helper BarHelper
|
30
|
-
end
|
10
|
+
(Path.dir/:fixtures).glob("*.rb").each{|f| require f.without_extension}
|
31
11
|
|
32
12
|
def fixtures_path
|
33
13
|
Path.dir/"../examples/bool_expr"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sexpr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-25 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: epath
|
16
|
-
requirement: &
|
16
|
+
requirement: &81881430 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.0.1
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *81881430
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: citrus
|
27
|
-
requirement: &
|
27
|
+
requirement: &81881110 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '2.4'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *81881110
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake
|
38
|
-
requirement: &
|
38
|
+
requirement: &81880830 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,21 +43,21 @@ dependencies:
|
|
43
43
|
version: 0.9.2
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *81880830
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rspec
|
49
|
-
requirement: &
|
49
|
+
requirement: &81880580 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 2.8
|
54
|
+
version: '2.8'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *81880580
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: wlang
|
60
|
-
requirement: &
|
60
|
+
requirement: &81880280 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,7 +65,7 @@ dependencies:
|
|
65
65
|
version: 0.10.2
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *81880280
|
69
69
|
description: Sexpr helps manipulating s-expressions in ruby.
|
70
70
|
email:
|
71
71
|
- blambeau@gmail.com
|
@@ -131,8 +131,9 @@ files:
|
|
131
131
|
- spec/rewriter/test_copy_and_apply.rb
|
132
132
|
- spec/processor/test_helper.rb
|
133
133
|
- spec/processor/test_sexpr_coercions.rb
|
134
|
-
- spec/processor/test_main_processor.rb
|
135
134
|
- spec/processor/test_build_helper_chain.rb
|
135
|
+
- spec/processor/test_use.rb
|
136
|
+
- spec/processor/test_apply.rb
|
136
137
|
- spec/processor/test_call.rb
|
137
138
|
- spec/processor/helper/test_call.rb
|
138
139
|
- spec/test_rewriter.rb
|
@@ -163,6 +164,10 @@ files:
|
|
163
164
|
- spec/node/test_sexpr_body.rb
|
164
165
|
- spec/node/test_sexpr_type.rb
|
165
166
|
- spec/test_readme_examples.rb
|
167
|
+
- spec/fixtures/preprocessed.rb
|
168
|
+
- spec/fixtures/simple_processor.rb
|
169
|
+
- spec/fixtures/bar.rb
|
170
|
+
- spec/fixtures/foo.rb
|
166
171
|
- tasks/debug_mail.rake
|
167
172
|
- tasks/yard.rake
|
168
173
|
- tasks/gem.rake
|
@@ -181,9 +186,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
181
186
|
- - ! '>='
|
182
187
|
- !ruby/object:Gem::Version
|
183
188
|
version: '0'
|
184
|
-
segments:
|
185
|
-
- 0
|
186
|
-
hash: -185808739
|
187
189
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
190
|
none: false
|
189
191
|
requirements:
|
@@ -215,8 +217,9 @@ test_files:
|
|
215
217
|
- spec/rewriter/test_copy_and_apply.rb
|
216
218
|
- spec/processor/test_helper.rb
|
217
219
|
- spec/processor/test_sexpr_coercions.rb
|
218
|
-
- spec/processor/test_main_processor.rb
|
219
220
|
- spec/processor/test_build_helper_chain.rb
|
221
|
+
- spec/processor/test_use.rb
|
222
|
+
- spec/processor/test_apply.rb
|
220
223
|
- spec/processor/test_call.rb
|
221
224
|
- spec/processor/helper/test_call.rb
|
222
225
|
- spec/test_rewriter.rb
|
@@ -247,3 +250,7 @@ test_files:
|
|
247
250
|
- spec/node/test_sexpr_body.rb
|
248
251
|
- spec/node/test_sexpr_type.rb
|
249
252
|
- spec/test_readme_examples.rb
|
253
|
+
- spec/fixtures/preprocessed.rb
|
254
|
+
- spec/fixtures/simple_processor.rb
|
255
|
+
- spec/fixtures/bar.rb
|
256
|
+
- spec/fixtures/foo.rb
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
module Sexpr
|
3
|
-
describe Processor, "main_processor" do
|
4
|
-
|
5
|
-
let(:procclass){ Class.new(Processor) }
|
6
|
-
|
7
|
-
it 'defaults to self' do
|
8
|
-
proc = procclass.new
|
9
|
-
proc.main_processor.should eq(proc)
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'may be specified through options' do
|
13
|
-
proc = procclass.new(:main_processor => :hello)
|
14
|
-
proc.main_processor.should eq(:hello)
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
end
|