]> git.wincent.com - walrat.git/blob - spec/walrat/memoizing_cache_spec.rb
Initial import (extraction from Walrus repo, commit 0c9d44c)
[walrat.git] / spec / walrat / memoizing_cache_spec.rb
1 # Copyright 2007-2010 Wincent Colaiuta. All rights reserved.
2 # Redistribution and use in source and binary forms, with or without
3 # modification, are permitted provided that the following conditions are met:
4 #
5 # 1. Redistributions of source code must retain the above copyright notice,
6 #    this list of conditions and the following disclaimer.
7 # 2. Redistributions in binary form must reproduce the above copyright notice,
8 #    this list of conditions and the following disclaimer in the documentation
9 #    and/or other materials provided with the distribution.
10 #
11 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
12 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
15 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
16 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
17 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
18 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
19 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21 # POSSIBILITY OF SUCH DAMAGE.
22
23 require File.expand_path('../spec_helper', File.dirname(__FILE__))
24
25 describe Walrat::MemoizingCache::NoValueForKey do
26   it 'is a singleton' do
27     expect do
28       Walrat::MemoizingCache::NoValueForKey.new
29     end.to raise_error(NoMethodError, /private method/)
30
31     Walrat::MemoizingCache::NoValueForKey.instance.object_id.
32       should == Walrat::MemoizingCache::NoValueForKey.instance.object_id
33   end
34
35   it 'should be able to use NoValueForKey as the default value for a hash' do
36     hash = Hash.new Walrat::MemoizingCache::NoValueForKey.instance
37     hash.default.should == Walrat::MemoizingCache::NoValueForKey.instance
38     hash[:foo].should == Walrat::MemoizingCache::NoValueForKey.instance
39     hash[:foo] = 'bar'
40     hash[:foo].should == 'bar'
41     hash[:bar].should == Walrat::MemoizingCache::NoValueForKey.instance
42   end
43 end
44
45 describe Walrat::MemoizingCache do
46   it 'parses with memoizing turned on'
47   it 'parses with memoizing turned off'
48   specify 'parsing with memoization turned on is faster'
49 end
50
51 # left-recursion is enabled by code in the memoizer and elsewhere; keep the
52 # specs here for want of a better place
53 describe 'working with left-recursive rules' do
54   specify 'circular rules should cause a short-circuit' do
55     class InfiniteLoop < Walrat::Grammar
56       starting_symbol :a
57       rule            :a, :a # a bone-headed rule
58     end
59
60     grammar = InfiniteLoop.new
61     expect do
62       grammar.parse('anything')
63     end.to raise_error(Walrat::LeftRecursionException)
64   end
65
66   specify 'shortcuiting is not be fatal if a valid alternative is present' do
67     class AlmostInfinite < Walrat::Grammar
68       starting_symbol :a
69       rule            :a, :a | :b # slightly less bone-headed
70       rule            :b, 'foo'
71     end
72
73     grammar = AlmostInfinite.new
74     grammar.parse('foo').should == 'foo'
75   end
76
77   it 'retries after short-circuiting if valid continuation point' do
78     class MuchMoreRealisticExample < Walrat::Grammar
79       starting_symbol :a
80       rule            :a, :a & :b | :b
81       rule            :b, 'foo'
82     end
83
84     # note the right associativity
85     grammar = MuchMoreRealisticExample.new
86     grammar.parse('foo').should == 'foo'
87     grammar.parse('foofoo').should == ['foo', 'foo']
88     grammar.parse('foofoofoo').should == [['foo', 'foo'], 'foo']
89     grammar.parse('foofoofoofoo').should == [[['foo', 'foo'], 'foo'], 'foo']
90     grammar.parse('foofoofoofoofoo').should == [[[['foo', 'foo'], 'foo'], 'foo'], 'foo']
91   end
92
93   specify 'right associativity should work when building AST nodes' do
94     class RightAssociativeAdditionExample < Walrat::Grammar
95       starting_symbol :addition_expression
96       rule            :term, /\d+/
97       rule            :addition_expression,
98                       :addition_expression & '+'.skip & :term | :term
99       node            :addition_expression
100       production      :addition_expression, :left, :right
101
102       # TODO: syntax for expressing alternate production?
103     end
104
105     pending
106     grammar = RightAssociativeAdditionExample.new
107     result = grammar.parse('1+2')
108   end
109 end