sexpr 0.2.0 → 0.3.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 +24 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/LICENCE.md +1 -1
- data/Manifest.txt +1 -0
- data/README.md +46 -31
- data/examples/bool_expr/bool_expr.citrus +72 -0
- data/examples/bool_expr/bool_expr.rb +86 -0
- data/examples/bool_expr/bool_expr.sexp.yml +23 -0
- data/lib/sexpr.rb +27 -20
- data/lib/sexpr/errors.rb +15 -0
- data/lib/sexpr/grammar.rb +21 -77
- data/lib/sexpr/grammar/matching.rb +56 -0
- data/lib/sexpr/grammar/options.rb +53 -0
- data/lib/sexpr/grammar/parsing.rb +20 -0
- data/lib/sexpr/grammar/tagging.rb +49 -0
- data/lib/sexpr/loader.rb +0 -1
- data/lib/sexpr/matcher.rb +15 -0
- data/lib/sexpr/matcher/alternative.rb +30 -0
- data/lib/sexpr/matcher/many.rb +54 -0
- data/lib/sexpr/matcher/reference.rb +32 -0
- data/lib/sexpr/matcher/rule.rb +31 -0
- data/lib/sexpr/matcher/sequence.rb +30 -0
- data/lib/sexpr/matcher/terminal.rb +37 -0
- data/lib/sexpr/node.rb +16 -0
- data/lib/sexpr/parser.rb +48 -0
- data/lib/sexpr/parser/citrus.rb +67 -0
- data/lib/sexpr/version.rb +2 -2
- data/sexpr.gemspec +1 -0
- data/sexpr.noespec +2 -1
- data/spec/grammar/matching/test_compile_rule.rb +23 -0
- data/spec/grammar/matching/test_compile_rule_defn.rb +103 -0
- data/spec/grammar/options/test_install_parser.rb +36 -0
- data/spec/grammar/options/test_install_path.rb +19 -0
- data/spec/grammar/options/test_install_root.rb +27 -0
- data/spec/grammar/tagging/test_looks_a_sexpr.rb +20 -0
- data/spec/grammar/tagging/test_mod2rulename.rb +19 -0
- data/spec/grammar/tagging/test_rule2modname.rb +19 -0
- data/spec/grammar/tagging/test_tag_sexpr.rb +28 -0
- data/spec/grammar/test_new.rb +15 -0
- data/spec/grammar/test_parse.rb +27 -18
- data/spec/grammar/test_sexpr.rb +53 -0
- data/spec/{alternative → matcher/alternative}/test_eat.rb +1 -1
- data/spec/{alternative → matcher/alternative}/test_match_q.rb +1 -1
- data/spec/{many → matcher/many}/test_eat.rb +1 -1
- data/spec/{many → matcher/many}/test_initialize.rb +1 -1
- data/spec/{many → matcher/many}/test_match_q.rb +1 -1
- data/spec/{reference → matcher/reference}/test_eat.rb +1 -1
- data/spec/{reference → matcher/reference}/test_match_q.rb +1 -1
- data/spec/{rule → matcher/rule}/test_eat.rb +1 -1
- data/spec/{rule → matcher/rule}/test_match_q.rb +1 -1
- data/spec/{sequence → matcher/sequence}/test_eat.rb +1 -1
- data/spec/{sequence → matcher/sequence}/test_match_q.rb +1 -1
- data/spec/{terminal → matcher/terminal}/test_eat.rb +1 -1
- data/spec/{terminal → matcher/terminal}/test_match_q.rb +1 -1
- data/spec/{terminal → matcher/terminal}/test_terminal_match.rb +1 -1
- data/spec/node/test_sexpr_body.rb +18 -0
- data/spec/node/test_sexpr_type.rb +14 -0
- data/spec/parser/citrus/test_new.rb +28 -0
- data/spec/parser/citrus/test_parse.rb +40 -0
- data/spec/parser/citrus/test_recognize.rb +18 -0
- data/spec/parser/citrus/test_registration.rb +20 -0
- data/spec/parser/citrus/test_to_sexpr.rb +16 -0
- data/spec/parser/test_factor.rb +17 -0
- data/spec/parser/test_input_text.rb +27 -0
- data/spec/spec_helper.rb +18 -1
- data/spec/test_load.rb +40 -13
- data/spec/test_readme_examples.rb +40 -30
- data/spec/test_sexpr.rb +1 -1
- metadata +118 -68
- data/lib/sexpr/alternative.rb +0 -28
- data/lib/sexpr/element.rb +0 -9
- data/lib/sexpr/many.rb +0 -52
- data/lib/sexpr/reference.rb +0 -30
- data/lib/sexpr/rule.rb +0 -29
- data/lib/sexpr/sequence.rb +0 -28
- data/lib/sexpr/terminal.rb +0 -35
- data/spec/bool_expr.yml +0 -19
- data/spec/grammar/test_compile_rule.rb +0 -25
- data/spec/grammar/test_compile_rule_defn.rb +0 -98
- data/spec/grammar/test_fetch.rb +0 -18
- data/spec/grammar/test_root.rb +0 -20
- data/spec/test_bool_expr.rb +0 -27
data/lib/sexpr/reference.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
module Sexpr
|
2
|
-
class Reference
|
3
|
-
include Element
|
4
|
-
|
5
|
-
attr_reader :rule_name
|
6
|
-
attr_reader :grammar
|
7
|
-
|
8
|
-
def initialize(rule_name, grammar)
|
9
|
-
@rule_name = rule_name
|
10
|
-
@grammar = grammar
|
11
|
-
end
|
12
|
-
|
13
|
-
def rule
|
14
|
-
@rule ||= @grammar[@rule_name]
|
15
|
-
end
|
16
|
-
|
17
|
-
def match?(sexp)
|
18
|
-
rule && rule.match?(sexp)
|
19
|
-
end
|
20
|
-
|
21
|
-
def eat(sexp)
|
22
|
-
rule && rule.eat(sexp)
|
23
|
-
end
|
24
|
-
|
25
|
-
def inspect
|
26
|
-
"(ref #{rule_name}, #{rule.inspect})"
|
27
|
-
end
|
28
|
-
|
29
|
-
end # class Reference
|
30
|
-
end # module Sexpr
|
data/lib/sexpr/rule.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
module Sexpr
|
2
|
-
class Rule
|
3
|
-
include Element
|
4
|
-
|
5
|
-
attr_reader :name
|
6
|
-
attr_reader :defn
|
7
|
-
|
8
|
-
def initialize(name, defn)
|
9
|
-
@name = name
|
10
|
-
@defn = defn
|
11
|
-
end
|
12
|
-
|
13
|
-
def match?(sexp)
|
14
|
-
return nil unless sexp.is_a?(Array)
|
15
|
-
return false unless sexp.first && (sexp.first == name)
|
16
|
-
defn.match?(sexp[1..-1])
|
17
|
-
end
|
18
|
-
|
19
|
-
def eat(sexp)
|
20
|
-
return nil unless match?(sexp.first)
|
21
|
-
sexp[1..-1]
|
22
|
-
end
|
23
|
-
|
24
|
-
def inspect
|
25
|
-
"(rule #{name}, #{defn.inspect})"
|
26
|
-
end
|
27
|
-
|
28
|
-
end # class Rule
|
29
|
-
end # module Sexpr
|
data/lib/sexpr/sequence.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
module Sexpr
|
2
|
-
class Sequence
|
3
|
-
include Element
|
4
|
-
|
5
|
-
attr_reader :terms
|
6
|
-
|
7
|
-
def initialize(terms)
|
8
|
-
@terms = terms
|
9
|
-
end
|
10
|
-
|
11
|
-
def match?(sexp)
|
12
|
-
return nil unless sexp.is_a?(Array)
|
13
|
-
eat = eat(sexp)
|
14
|
-
eat && eat.empty?
|
15
|
-
end
|
16
|
-
|
17
|
-
def eat(sexp)
|
18
|
-
@terms.inject sexp do |rest,rule|
|
19
|
-
rest && rule.eat(rest)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def inspect
|
24
|
-
"(seq #{terms.inspect})"
|
25
|
-
end
|
26
|
-
|
27
|
-
end # class Sequence
|
28
|
-
end # module Sexpr
|
data/lib/sexpr/terminal.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
module Sexpr
|
2
|
-
class Terminal
|
3
|
-
include Element
|
4
|
-
|
5
|
-
attr_reader :value
|
6
|
-
|
7
|
-
def initialize(value)
|
8
|
-
@value = value
|
9
|
-
end
|
10
|
-
|
11
|
-
def inspect
|
12
|
-
"(terminal #{value.inspect})"
|
13
|
-
end
|
14
|
-
|
15
|
-
def match?(sexp)
|
16
|
-
terminal_match?(sexp)
|
17
|
-
end
|
18
|
-
|
19
|
-
def eat(sexp)
|
20
|
-
match?(sexp.first) ? sexp[1..-1] : nil
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def terminal_match?(term)
|
26
|
-
case @value
|
27
|
-
when Regexp
|
28
|
-
@value === term rescue false
|
29
|
-
when TrueClass, FalseClass, NilClass
|
30
|
-
@value == term
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
end # class Terminal
|
35
|
-
end # module Sexpr
|
data/spec/bool_expr.yml
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
bool_expr:
|
2
|
-
- bool_and
|
3
|
-
- bool_or
|
4
|
-
- bool_not
|
5
|
-
- var_ref
|
6
|
-
- bool_lit
|
7
|
-
bool_and:
|
8
|
-
- [ bool_expr+ ]
|
9
|
-
bool_or:
|
10
|
-
- [ bool_expr+ ]
|
11
|
-
bool_not:
|
12
|
-
- [ bool_expr ]
|
13
|
-
var_ref:
|
14
|
-
- [ var_name ]
|
15
|
-
var_name:
|
16
|
-
!ruby/regexp /^[a-z]+$/
|
17
|
-
bool_lit:
|
18
|
-
- true
|
19
|
-
- false
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
module Sexpr
|
3
|
-
class Grammar; public :compile_rule; end
|
4
|
-
describe Grammar, "compile_rule" do
|
5
|
-
|
6
|
-
def compile(name, arg)
|
7
|
-
Grammar.new.compile_rule(name, arg)
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'keep alternatives unchanged' do
|
11
|
-
compile(:hello, Alternative.new([]) ).should be_a(Alternative)
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'keep terminals unchanged' do
|
15
|
-
compile(:hello, Terminal.new(true) ).should be_a(Terminal)
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'keep creates a Rule englobing sequences' do
|
19
|
-
compiled = compile(:hello, Sequence.new([]) )
|
20
|
-
compiled.should be_a(Rule)
|
21
|
-
compiled.name.should eq(:hello)
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
module Sexpr
|
3
|
-
class Grammar; public :compile_rule_defn; end
|
4
|
-
describe Grammar, "compile_rule_defn" do
|
5
|
-
|
6
|
-
let(:grammar){ Grammar.new }
|
7
|
-
subject{ grammar.compile_rule_defn(arg) }
|
8
|
-
|
9
|
-
context 'with an Element' do
|
10
|
-
let(:arg){ Terminal.new(//) }
|
11
|
-
it 'returns arg itself' do
|
12
|
-
subject.should eq(arg)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context "with true" do
|
17
|
-
let(:arg){ true }
|
18
|
-
it 'gives it true' do
|
19
|
-
subject.should be_a(Terminal)
|
20
|
-
subject.value.should eq(true)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context "with false" do
|
25
|
-
let(:arg){ false }
|
26
|
-
it 'gives it false' do
|
27
|
-
subject.should be_a(Terminal)
|
28
|
-
subject.value.should eq(false)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context "with nil" do
|
33
|
-
let(:arg){ nil }
|
34
|
-
it 'gives it nil' do
|
35
|
-
subject.should be_a(Terminal)
|
36
|
-
subject.value.should eq(nil)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'with an alternative array' do
|
41
|
-
let(:arg){ [true, false, nil] }
|
42
|
-
it 'factors an Alternative' do
|
43
|
-
subject.should be_a(Alternative)
|
44
|
-
end
|
45
|
-
it 'compiles its elements' do
|
46
|
-
subject.terms.size.should eq(3)
|
47
|
-
subject.terms.all?{|x| x.is_a?(Terminal)}.should be_true
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
context 'with a sequence array' do
|
52
|
-
let(:arg){ [[true, false, nil]] }
|
53
|
-
it 'factors a Sequence' do
|
54
|
-
subject.should be_a(Sequence)
|
55
|
-
end
|
56
|
-
it 'compiles its elements' do
|
57
|
-
subject.terms.size.should eq(3)
|
58
|
-
subject.terms.all?{|x| x.is_a?(Terminal)}.should be_true
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
context 'with subalternatives' do
|
63
|
-
let(:arg){ [ ["a_rule", [false, true, nil] ]] }
|
64
|
-
it 'compiles the last as an Alternative' do
|
65
|
-
subject.terms.last.should be_a(Alternative)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
context 'with a reference to a non-terminal' do
|
70
|
-
let(:arg){ "a_rule" }
|
71
|
-
it 'factors a Reference' do
|
72
|
-
subject.should be_a(Reference)
|
73
|
-
end
|
74
|
-
it 'refers to the appropriate rule name' do
|
75
|
-
subject.rule_name.should eq(:a_rule)
|
76
|
-
end
|
77
|
-
it 'refers to the appropriate grammar' do
|
78
|
-
subject.grammar.should eq(grammar)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context 'with a stared non-terminal' do
|
83
|
-
let(:arg){ "a_rule+" }
|
84
|
-
it 'factors a Many' do
|
85
|
-
subject.should be_a(Many)
|
86
|
-
end
|
87
|
-
it 'refers to the appropriate rule' do
|
88
|
-
subject.term.should be_a(Reference)
|
89
|
-
subject.term.rule_name.should eq(:a_rule)
|
90
|
-
end
|
91
|
-
it 'refers to the appropriate multiplicities' do
|
92
|
-
subject.min.should eq(1)
|
93
|
-
subject.max.should be_nil
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
98
|
-
end
|
data/spec/grammar/test_fetch.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
module Sexpr
|
3
|
-
describe Grammar, "fetch" do
|
4
|
-
|
5
|
-
let(:grammar){
|
6
|
-
Sexpr.load(:terminal => /[a-z]+/)
|
7
|
-
}
|
8
|
-
|
9
|
-
it 'returns the rule when it exists' do
|
10
|
-
grammar[:terminal].should be_a(Terminal)
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'returns nil otherwise' do
|
14
|
-
grammar[:nosuchone].should be_nil
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
end # module Sexpr
|
data/spec/grammar/test_root.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
module Sexpr
|
3
|
-
describe Grammar, "root" do
|
4
|
-
|
5
|
-
let(:rules){ {:t => /[a-z]+/, :nt => true} }
|
6
|
-
|
7
|
-
def grammar(options = {})
|
8
|
-
Sexpr.load(rules, options)
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'is the first key by default' do
|
12
|
-
grammar.root.value.should eq(/[a-z]+/)
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'is the specified rule when specified' do
|
16
|
-
grammar(:root => :nt).root.value.should eq(true)
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|
data/spec/test_bool_expr.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
module Sexpr
|
3
|
-
describe "the bool_expr grammar" do
|
4
|
-
|
5
|
-
let(:g){ Sexpr.load(Path.dir/"bool_expr.yml") }
|
6
|
-
|
7
|
-
it "allows checking validy of specific nodes" do
|
8
|
-
(g[:bool_lit] === true).should be_true
|
9
|
-
(g[:var_ref] === [:var_ref, "x"]).should be_true
|
10
|
-
(g[:bool_and] === [:bool_and, true, false]).should be_true
|
11
|
-
(g[:bool_and] === [:bool_or, true, false]).should be_false
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'allows checking the validity against the root rule' do
|
15
|
-
(g === true).should be_true
|
16
|
-
(g === false).should be_true
|
17
|
-
(g === [:bool_not, true]).should be_true
|
18
|
-
(g === [:var_ref, "x"]).should be_true
|
19
|
-
(g === [:bool_not, [:var_ref, "x"]]).should be_true
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'detects wrong matches' do
|
23
|
-
(g === [:bool_not, [:something_else, "x"]]).should be_false
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|