hipe-gorillagrammar 0.0.1beta
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +21 -0
- data/History.txt +8 -0
- data/LICENSE.txt +19 -0
- data/README.txt +11 -0
- data/Rakefile +25 -0
- data/Thorfile +135 -0
- data/hipe-gorillagrammar.gemspec +66 -0
- data/lib/hipe-gorillagrammar/extensions/syntax.rb +50 -0
- data/lib/hipe-gorillagrammar.rb +492 -0
- data/spec/argv.rb +3 -0
- data/spec/extensions/syntax_spec.rb +41 -0
- data/spec/grammar_spec.rb +91 -0
- data/spec/helpers.rb +5 -0
- data/spec/parse_tree_spec.rb +64 -0
- data/spec/parsing_spec.rb +304 -0
- data/spec/range_spec.rb +47 -0
- data/spec/regexp_spec.rb +24 -0
- data/spec/runtime_spec.rb +66 -0
- data/spec/sequence_spec.rb +85 -0
- data/spec/shorthand_spec.rb +186 -0
- data/spec/spec.opts +4 -0
- data/spec/symbol_reference_spec.rb +28 -0
- data/spec/symbol_spec.rb +45 -0
- metadata +88 -0
data/spec/range_spec.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# rake spec SPEC=spec/range_spec.rb
|
2
|
+
require 'hipe-gorillagrammar'
|
3
|
+
|
4
|
+
module Hipe
|
5
|
+
|
6
|
+
describe GorillaGrammar::RangeOf do
|
7
|
+
|
8
|
+
it "should not allow an empty grammar" do
|
9
|
+
lambda {
|
10
|
+
Hipe.GorillaGrammar { zero_or_more() }
|
11
|
+
}.should raise_error(GorillaGrammar::GrammarGrammarException, 'Arguments must be non-zero length')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should pass if the grammar allows it" do
|
15
|
+
grammar = Hipe.GorillaGrammar do
|
16
|
+
zero_or_more 'a','b','c'
|
17
|
+
end
|
18
|
+
result = grammar.parse []
|
19
|
+
result.should be_a_kind_of GorillaGrammar::ParseTree
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should fail unless the grammar allows it" do
|
23
|
+
grammar = Hipe.GorillaGrammar do
|
24
|
+
one_or_more 'a','b','c'
|
25
|
+
end
|
26
|
+
result = grammar.parse []
|
27
|
+
result.should be_a_kind_of GorillaGrammar::ParseFailure
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should parse several tokens" do
|
31
|
+
grammar = Hipe.GorillaGrammar do
|
32
|
+
one_or_more 'a','b','c'
|
33
|
+
end
|
34
|
+
result = grammar.parse ['a','b','b','a']
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should inspect as a grammar" do
|
38
|
+
g = Hipe.GorillaGrammar { :sammy =~ (1..more).of('a','b','c') }
|
39
|
+
s = g.inspect
|
40
|
+
s.should match %r|sammy.*1.*"a".*"b".*"c"|m
|
41
|
+
end
|
42
|
+
|
43
|
+
it "is unlikely to have a minimum of two or more" do
|
44
|
+
Hipe.GorillaGrammar{(2..more).of('jon','ringo','george','paul')}.parse(['jon','ringo']).is_error?.should == false
|
45
|
+
end
|
46
|
+
end # when given non-zero
|
47
|
+
end
|
data/spec/regexp_spec.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#rake spec SPEC=spec/regexp_spec.rb
|
2
|
+
require 'hipe-gorillagrammar'
|
3
|
+
include Hipe::GorillaGrammar
|
4
|
+
|
5
|
+
|
6
|
+
describe RegexpTerminal, 'in the context of parsing' do
|
7
|
+
before :all do
|
8
|
+
@g = Hipe.GorillaGrammar {
|
9
|
+
:sentence =~ [:color[/^(red|green)$/], 'beans', 'and', :food[/^salad|rice$/]]
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
it "cannot parse on its own" do
|
14
|
+
g = Hipe.GorillaGrammar{ :item =~ // }
|
15
|
+
lambda{ t = g.parse ['alpha'] }.should raise_error NoMethodError, /undefined method `parse'/
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should fail with simple regexp" do
|
19
|
+
g = @g
|
20
|
+
tree = @g.parse(['blue','beans','and','rice'])
|
21
|
+
tree.is_error?.should == true
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#rake spec SPEC=spec/runtime_spec.rb
|
2
|
+
require 'hipe-gorillagrammar'
|
3
|
+
include Hipe::GorillaGrammar
|
4
|
+
|
5
|
+
describe Runtime do
|
6
|
+
|
7
|
+
it "shortcuts should fail" do
|
8
|
+
lambda {
|
9
|
+
Runtime.not_there
|
10
|
+
}.should raise_error(NoMethodError)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return nil" do
|
14
|
+
Runtime.current_grammar.should == nil
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return nil again" do
|
18
|
+
Runtime.current_grammar.should == nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should throw when there's no current grammar" do
|
22
|
+
lambda{
|
23
|
+
Runtime.current_grammar!
|
24
|
+
}.should raise_error(UsageFailure)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should work violently" do
|
28
|
+
g = nil
|
29
|
+
Hipe::GorillaGrammar.define {
|
30
|
+
g = Runtime.current_grammar!
|
31
|
+
['']
|
32
|
+
}
|
33
|
+
g.should be_an_instance_of Grammar
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should work calmly" do
|
37
|
+
g = nil
|
38
|
+
Hipe::GorillaGrammar.define {
|
39
|
+
g = Runtime.current_grammar
|
40
|
+
['']
|
41
|
+
}
|
42
|
+
g.should be_an_instance_of Grammar
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should not allow doubles" do
|
46
|
+
lambda{
|
47
|
+
Hipe::GorillaGrammar.define {
|
48
|
+
Hipe::GorillaGrammar.define {}
|
49
|
+
['']
|
50
|
+
}
|
51
|
+
}.should raise_error(UsageFailure)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should work after" do
|
55
|
+
Hipe::GorillaGrammar.define {['']}
|
56
|
+
Runtime.current_grammar.should == nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "grammar can only take symbols" do
|
60
|
+
g = Hipe::GorillaGrammar.define {['']}
|
61
|
+
lambda{ g[:a_symbol] = :not_a_symbol }.should raise_error(
|
62
|
+
GorillaException, %{Expecting GorillaSymbol had :not_a_symbol}
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#rake spec SPEC=spec/sequence_spec.rb
|
2
|
+
require 'hipe-gorillagrammar'
|
3
|
+
|
4
|
+
module Hipe
|
5
|
+
|
6
|
+
describe GorillaGrammar::Sequence do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@abc = Hipe.GorillaGrammar do
|
10
|
+
sequence 'a','b','c'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should fail on empty sequence (s1)" do
|
15
|
+
lambda {
|
16
|
+
Hipe.GorillaGrammar { sequence() }
|
17
|
+
}.should raise_error(GorillaGrammar::GrammarGrammarException, 'Arguments must be non-zero length')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should fail on empty input (s2)" do
|
21
|
+
result = @abc.parse []
|
22
|
+
result.should be_a_kind_of GorillaGrammar::ParseFailure
|
23
|
+
end
|
24
|
+
|
25
|
+
class MockyOneOff; # we couldn't use rspec for this because of marshaling
|
26
|
+
include GorillaGrammar::GorillaSymbol
|
27
|
+
def match(a); :/ ; end
|
28
|
+
def status; :/ end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should compalin when symbol returns bad status (s3)" do
|
32
|
+
mok = MockyOneOff.new
|
33
|
+
g = Hipe.GorillaGrammar do
|
34
|
+
:a =~ mok
|
35
|
+
:sentence =~ [:a]
|
36
|
+
end
|
37
|
+
lambda{g.parse ['a','b'] }.should raise_error(GorillaGrammar::GorillaException, /bad status/)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should parse a simple one (s4)" do
|
41
|
+
result = @abc.parse ['a','b','c']
|
42
|
+
result.should be_a_kind_of GorillaGrammar::ParseTree
|
43
|
+
result.should == ['a','b','c']
|
44
|
+
end
|
45
|
+
|
46
|
+
# s5 moved to parsing spec
|
47
|
+
|
48
|
+
it "should work for simple compound (s6)" do
|
49
|
+
grammar = Hipe.GorillaGrammar do
|
50
|
+
sequence one_or_more('b','e'),'c'
|
51
|
+
end
|
52
|
+
result = grammar.parse ['b','c']
|
53
|
+
result.is_error?.should == false
|
54
|
+
result.to_a.should == [['b'],'c']
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should parse a little more complex (s7)" do
|
58
|
+
grammar = Hipe.GorillaGrammar do
|
59
|
+
sequence 'a',one_or_more('b','e'),'c'
|
60
|
+
end
|
61
|
+
result = grammar.parse(['a','b','e','b','c'])
|
62
|
+
result.is_error?.should == false
|
63
|
+
result.to_a.should == ['a',['b','e','b'],'c']
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should render expecting message jumping btwn two frames (s8)" do
|
67
|
+
grammar = Hipe.GorillaGrammar do
|
68
|
+
sequence zero_or_more('b','e'),'c'
|
69
|
+
end
|
70
|
+
result = grammar.parse(['d'])
|
71
|
+
result.is_error?.should == true
|
72
|
+
result.message.should match(/expecting(:? you to say)? "b", "e" or "c"/)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should handle zero or more at begin(s9)" do
|
76
|
+
grammar = Hipe.GorillaGrammar do
|
77
|
+
sequence zero_or_more('b','e'),'c'
|
78
|
+
end
|
79
|
+
result = grammar.parse(['b','e','c'])
|
80
|
+
result.is_error?.should == false
|
81
|
+
result.to_a.should == [['b','e'],'c']
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
#rake spec SPEC=spec/shorthand_spec.rb
|
2
|
+
require File.dirname(__FILE__)+'/helpers.rb'
|
3
|
+
require 'hipe-gorillagrammar'
|
4
|
+
include Hipe::GorillaGrammar
|
5
|
+
|
6
|
+
class Grammar
|
7
|
+
include Helpers
|
8
|
+
# only for irb -- tokenize a string thru the shell. careful!
|
9
|
+
def parz str;
|
10
|
+
tox = shell!(str);
|
11
|
+
puts "your tokens tokenized from shell:"
|
12
|
+
pp tox
|
13
|
+
parse tox
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Hipe::GorillaGrammar, " in the context of Shorthands" do
|
18
|
+
it "should bark on missing method" do
|
19
|
+
lambda {
|
20
|
+
Hipe::GorillaGrammar.define {
|
21
|
+
bork()
|
22
|
+
}
|
23
|
+
}.should raise_error(NameError)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should bark when undefined rangeof method (h1)" do
|
27
|
+
Grammar.register_shorthand :nonexistant_method, RangeOf
|
28
|
+
lambda{
|
29
|
+
Hipe.GorillaGrammar{ nonexistant_method('x') }
|
30
|
+
}.should raise_error(UsageFailure, /invalid name str/)
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
it "every one should construct (h2)" do
|
35
|
+
a = {}
|
36
|
+
Hipe::GorillaGrammar(){
|
37
|
+
a[:ro56] = range_of( 5..6, 'alpha','beta','gamma')
|
38
|
+
a[:ro11] = one( 'delta','epsilon')
|
39
|
+
a[:ro01] = zero_or_one( 'zeta')
|
40
|
+
a[:ro1i] = one_or_more( 'eta','theta')
|
41
|
+
a[:ro0i] = zero_or_more( 'iota')
|
42
|
+
a[:seq1] = sequence( 'kappa','lambda','mu')
|
43
|
+
a[:rexp] = regexp( /^.$/)
|
44
|
+
}
|
45
|
+
a[:ro56].group.should == ["alpha","beta","gamma"]
|
46
|
+
a[:ro56].range.should == (5..6)
|
47
|
+
a[:ro11].group.should == ["delta","epsilon"]
|
48
|
+
a[:ro11].range.should == (1..1)
|
49
|
+
a[:ro01].group.should == ['zeta']
|
50
|
+
a[:ro01].range.should == (0..1)
|
51
|
+
a[:ro1i].group.should == ['eta','theta']
|
52
|
+
a[:ro1i].range.should == (1..Infinity)
|
53
|
+
a[:ro0i].group.should == ['iota']
|
54
|
+
a[:ro01].range.should == (0..1)
|
55
|
+
a[:seq1].group.should == ['kappa','lambda','mu']
|
56
|
+
a[:rexp].should == /^.$/
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should turn pipe into RangeOf (h3)" do
|
60
|
+
rangey = nil
|
61
|
+
g = Hipe.GorillaGrammar {
|
62
|
+
rangey = 'you' | 'i'
|
63
|
+
}
|
64
|
+
rangey.class.ancestors.include?(RangeOf).should == true
|
65
|
+
end
|
66
|
+
|
67
|
+
it "muliple strings with pipe (h4)" do
|
68
|
+
rangey = nil
|
69
|
+
g = Hipe.GorillaGrammar {
|
70
|
+
rangey = 'you' | 'i' | 'him'
|
71
|
+
}
|
72
|
+
rangey.class.ancestors.include?(RangeOf).should == true
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should do Fixnum.of (h5)" do
|
76
|
+
rangey = nil
|
77
|
+
g = Hipe.GorillaGrammar {
|
78
|
+
rangey = 1.of 'you','i'
|
79
|
+
}
|
80
|
+
rangey.class.ancestors.include?(RangeOf).should == true
|
81
|
+
end
|
82
|
+
|
83
|
+
it "different kind of pipies should be equal (h6)" do
|
84
|
+
range_of_1=range_of_2=range_of_3=range_of_4=range_of_5=target=nil
|
85
|
+
g = Hipe.GorillaGrammar {
|
86
|
+
range_of_1 = 1.of 'you','i','he'
|
87
|
+
range_of_2 = 'you' | 'i' | 'he'
|
88
|
+
range_of_3 = (1..1).of 'you','i','he'
|
89
|
+
range_of_4 = range_of 1..1, 'you','i','he'
|
90
|
+
range_of_5 = one 'you', 'i', 'he'
|
91
|
+
:main =~ ['']
|
92
|
+
}
|
93
|
+
target = RangeOf.new(1..1, ['you','i','he'])
|
94
|
+
target_str = target.inspect
|
95
|
+
target_str.should match(/.{11}/)
|
96
|
+
range_of_1.inspect.should == target_str
|
97
|
+
range_of_2.inspect.should == target_str
|
98
|
+
range_of_3.inspect.should == target_str
|
99
|
+
range_of_4.inspect.should == target_str
|
100
|
+
range_of_5.inspect.should == target_str
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should complain on bad symbol (h7)" do
|
104
|
+
lambda {
|
105
|
+
Hipe.GorillaGrammar {
|
106
|
+
:some_symbol =~ 123
|
107
|
+
}
|
108
|
+
}.should raise_error(UsageFailure, %{Can't determine symbol type for "123"})
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should complain on re-definition (h8)" do
|
112
|
+
lambda {
|
113
|
+
Hipe.GorillaGrammar {
|
114
|
+
:symbol =~ ['this']
|
115
|
+
:symbol =~ ['this']
|
116
|
+
}
|
117
|
+
}.should raise_error(GrammarGrammarException, %r{can't redefine symbol}i)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "two ways one grammar (h9)" do
|
121
|
+
g = Hipe.GorillaGrammar(:name =>:beuford) { :x =~ '.' }
|
122
|
+
Runtime.get_grammar(:beuford).should equal(g)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should store symbols (h10)" do
|
126
|
+
g = Hipe.GorillaGrammar(:name=>:grammar1) {
|
127
|
+
:subject =~ 'you'|'i'|'he'|'she'
|
128
|
+
:verb =~ 1.of('run','walk','blah')
|
129
|
+
:adverb =~ 'quickly'|'slowly'|['without', 'hesitation']
|
130
|
+
:predicate =~ (0..1).of(:adverb, :verb, :object[/^.*$/])
|
131
|
+
:sentence =~ [:subject,:predicate]
|
132
|
+
}
|
133
|
+
g[:subject ].inspect.should match /1.*1.*you.*i.*he.*she/
|
134
|
+
g[:verb ].inspect.should match /1.*1.*run.*walk.*blah/
|
135
|
+
g[:adverb ].inspect.should match /1.*1.*quickly.*slowly.*without.*hesitation/
|
136
|
+
g[:predicate ].inspect.should match /0.*1.*adverb.*verb.*object/
|
137
|
+
g[:sentence ].inspect.should match /subject.*predicate/
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should work with symbol references (h11)" do
|
141
|
+
g = Hipe.GorillaGrammar(:name=>:grammar2) {
|
142
|
+
:alpha =~ 'a'
|
143
|
+
:beta =~ 'b'
|
144
|
+
:gamma =~ 'c'
|
145
|
+
:sentence =~ [:alpha,:beta,:gamma]
|
146
|
+
}
|
147
|
+
result = g.parse ['a','b','c']
|
148
|
+
result.is_error?.should == false
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should report expecting right at the start of a branch (h12)" do
|
152
|
+
g = Hipe.GorillaGrammar {
|
153
|
+
:sentence =~ [
|
154
|
+
'i','want','my',
|
155
|
+
:manufacturer[1.of(['jimmy','dean'],['hickory','farms'])],
|
156
|
+
'sausage' ]
|
157
|
+
}
|
158
|
+
thing = g.parse ['i','want','my']
|
159
|
+
thing.is_error?.should == true
|
160
|
+
thing.should be_kind_of UnexpectedEndOfInput
|
161
|
+
thing.tree.expecting.should == %w("jimmy" "hickory") # strings with quotes in them
|
162
|
+
end
|
163
|
+
|
164
|
+
it "parse sequence 1 branch 2 x 2 x 1 (h13)" do
|
165
|
+
g = Hipe.GorillaGrammar {
|
166
|
+
:sentence =~ [:manufacturer[ one %w(jimmy dean), %w(hickory farms) ] ]
|
167
|
+
}
|
168
|
+
thing = g.parse []
|
169
|
+
thing.is_error?.should == true
|
170
|
+
thing.should be_kind_of UnexpectedEndOfInput
|
171
|
+
thing.tree.expecting.should == %w("jimmy" "hickory")
|
172
|
+
end
|
173
|
+
|
174
|
+
it "parse sequence 2 branch 2 x 2 x 1 (h14)" do
|
175
|
+
g = Hipe.GorillaGrammar {
|
176
|
+
:sentence =~ ['want','jimmy']
|
177
|
+
}
|
178
|
+
thing = g.parse ['want']
|
179
|
+
thing.is_error?.should == true
|
180
|
+
thing.should be_kind_of UnexpectedEndOfInput
|
181
|
+
thing.tree.expecting.should == %w("jimmy")
|
182
|
+
end
|
183
|
+
|
184
|
+
# h15 moved to another file (parsing)
|
185
|
+
|
186
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#rake spec SPEC=spec/symbol_reference_spec.rb
|
2
|
+
require 'hipe-gorillagrammar'
|
3
|
+
include Hipe::GorillaGrammar
|
4
|
+
|
5
|
+
describe SymbolReference do
|
6
|
+
|
7
|
+
# it "parse sequence 2 branch 2 x 2 x 1 trailing union w/o symbol references (sr1)" do
|
8
|
+
# g = Hipe.GorillaGrammar {
|
9
|
+
# :sentence =~ ['want', one( %w(jimmy dean), %w(hickory farms) ) ]
|
10
|
+
# }
|
11
|
+
# thing = g.parse ['want','jimmy']
|
12
|
+
# thing.is_error?.should == true
|
13
|
+
# thing.should be_kind_of UnexpectedEndOfInput
|
14
|
+
# thing.tree.expecting.should == %w("dean")
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
it "parse sequence 2 branch 2 x 2 x 1 (h15)" do
|
18
|
+
g = Hipe.GorillaGrammar {
|
19
|
+
:sentence =~ ['want', :manufacturer[ one %w(jimmy dean), %w(hickory farms) ] ]
|
20
|
+
}
|
21
|
+
# debugger
|
22
|
+
thing = g.parse ['want','jimmy']
|
23
|
+
thing.is_error?.should == true
|
24
|
+
thing.should be_kind_of UnexpectedEndOfInput
|
25
|
+
thing.tree.expecting.should == %w("dean")
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|