sexpr 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|