hipe-gorillagrammar 0.0.1beta
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/.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
|