sexpr 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/CHANGELOG.md +24 -1
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +2 -0
  4. data/LICENCE.md +1 -1
  5. data/Manifest.txt +1 -0
  6. data/README.md +46 -31
  7. data/examples/bool_expr/bool_expr.citrus +72 -0
  8. data/examples/bool_expr/bool_expr.rb +86 -0
  9. data/examples/bool_expr/bool_expr.sexp.yml +23 -0
  10. data/lib/sexpr.rb +27 -20
  11. data/lib/sexpr/errors.rb +15 -0
  12. data/lib/sexpr/grammar.rb +21 -77
  13. data/lib/sexpr/grammar/matching.rb +56 -0
  14. data/lib/sexpr/grammar/options.rb +53 -0
  15. data/lib/sexpr/grammar/parsing.rb +20 -0
  16. data/lib/sexpr/grammar/tagging.rb +49 -0
  17. data/lib/sexpr/loader.rb +0 -1
  18. data/lib/sexpr/matcher.rb +15 -0
  19. data/lib/sexpr/matcher/alternative.rb +30 -0
  20. data/lib/sexpr/matcher/many.rb +54 -0
  21. data/lib/sexpr/matcher/reference.rb +32 -0
  22. data/lib/sexpr/matcher/rule.rb +31 -0
  23. data/lib/sexpr/matcher/sequence.rb +30 -0
  24. data/lib/sexpr/matcher/terminal.rb +37 -0
  25. data/lib/sexpr/node.rb +16 -0
  26. data/lib/sexpr/parser.rb +48 -0
  27. data/lib/sexpr/parser/citrus.rb +67 -0
  28. data/lib/sexpr/version.rb +2 -2
  29. data/sexpr.gemspec +1 -0
  30. data/sexpr.noespec +2 -1
  31. data/spec/grammar/matching/test_compile_rule.rb +23 -0
  32. data/spec/grammar/matching/test_compile_rule_defn.rb +103 -0
  33. data/spec/grammar/options/test_install_parser.rb +36 -0
  34. data/spec/grammar/options/test_install_path.rb +19 -0
  35. data/spec/grammar/options/test_install_root.rb +27 -0
  36. data/spec/grammar/tagging/test_looks_a_sexpr.rb +20 -0
  37. data/spec/grammar/tagging/test_mod2rulename.rb +19 -0
  38. data/spec/grammar/tagging/test_rule2modname.rb +19 -0
  39. data/spec/grammar/tagging/test_tag_sexpr.rb +28 -0
  40. data/spec/grammar/test_new.rb +15 -0
  41. data/spec/grammar/test_parse.rb +27 -18
  42. data/spec/grammar/test_sexpr.rb +53 -0
  43. data/spec/{alternative → matcher/alternative}/test_eat.rb +1 -1
  44. data/spec/{alternative → matcher/alternative}/test_match_q.rb +1 -1
  45. data/spec/{many → matcher/many}/test_eat.rb +1 -1
  46. data/spec/{many → matcher/many}/test_initialize.rb +1 -1
  47. data/spec/{many → matcher/many}/test_match_q.rb +1 -1
  48. data/spec/{reference → matcher/reference}/test_eat.rb +1 -1
  49. data/spec/{reference → matcher/reference}/test_match_q.rb +1 -1
  50. data/spec/{rule → matcher/rule}/test_eat.rb +1 -1
  51. data/spec/{rule → matcher/rule}/test_match_q.rb +1 -1
  52. data/spec/{sequence → matcher/sequence}/test_eat.rb +1 -1
  53. data/spec/{sequence → matcher/sequence}/test_match_q.rb +1 -1
  54. data/spec/{terminal → matcher/terminal}/test_eat.rb +1 -1
  55. data/spec/{terminal → matcher/terminal}/test_match_q.rb +1 -1
  56. data/spec/{terminal → matcher/terminal}/test_terminal_match.rb +1 -1
  57. data/spec/node/test_sexpr_body.rb +18 -0
  58. data/spec/node/test_sexpr_type.rb +14 -0
  59. data/spec/parser/citrus/test_new.rb +28 -0
  60. data/spec/parser/citrus/test_parse.rb +40 -0
  61. data/spec/parser/citrus/test_recognize.rb +18 -0
  62. data/spec/parser/citrus/test_registration.rb +20 -0
  63. data/spec/parser/citrus/test_to_sexpr.rb +16 -0
  64. data/spec/parser/test_factor.rb +17 -0
  65. data/spec/parser/test_input_text.rb +27 -0
  66. data/spec/spec_helper.rb +18 -1
  67. data/spec/test_load.rb +40 -13
  68. data/spec/test_readme_examples.rb +40 -30
  69. data/spec/test_sexpr.rb +1 -1
  70. metadata +118 -68
  71. data/lib/sexpr/alternative.rb +0 -28
  72. data/lib/sexpr/element.rb +0 -9
  73. data/lib/sexpr/many.rb +0 -52
  74. data/lib/sexpr/reference.rb +0 -30
  75. data/lib/sexpr/rule.rb +0 -29
  76. data/lib/sexpr/sequence.rb +0 -28
  77. data/lib/sexpr/terminal.rb +0 -35
  78. data/spec/bool_expr.yml +0 -19
  79. data/spec/grammar/test_compile_rule.rb +0 -25
  80. data/spec/grammar/test_compile_rule_defn.rb +0 -98
  81. data/spec/grammar/test_fetch.rb +0 -18
  82. data/spec/grammar/test_root.rb +0 -20
  83. data/spec/test_bool_expr.rb +0 -27
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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