require 'cs_grammar' IGNORE='[]' describe "Grammar" do context "given axiom 'baaaaaa'" do context "with function b<a" do describe "#generate(x)" do it "should equal 'baaaaaa' at zero iteration" do Grammar.new('baaaaaa', {'b' => 'a', 'b<a' => 'b'}).generate(0).should == 'baaaaaa' end it "should equal 'abaaaaa' after one iteration" do Grammar.new('baaaaaa', {'b' => 'a', 'b<a' => 'b'}).generate(1).should == 'abaaaaa' end it "should equal 'aabaaaa' after one iteration" do Grammar.new('abaaaaa', {'b' => 'a', 'b<a' => 'b'}).generate(1).should == 'aabaaaa' end it "should equal 'aabaaaa' after two iterations" do Grammar.new('baaaaaa', {'b' => 'a', 'b<a' => 'b'}).generate(2).should == 'aabaaaa' end end end context "with function b<a and ignore []" do describe "#generate(x)" do it "should equal 'baaa[a]aa' at zero iteration" do Grammar.new('baaa[a]aa', {'b' => 'a', 'b<a' => 'b'}, IGNORE).generate(0).should == 'baaa[a]aa' end it "should equal 'abaaaaa' after one iteration" do Grammar.new('baaa[a]aa', {'b' => 'a', 'b<a' => 'b'}, IGNORE).generate(1).should == 'abaa[a]aa' end it "should equal 'aabaaaa' after one iteration" do Grammar.new('abaa[a]aa', {'b' => 'a', 'b<a' => 'b'}, IGNORE).generate(1).should == 'aaba[a]aa' end it "should equal 'aabaaaa' after two iterations" do Grammar.new('baaa[a]aa', {'b' => 'a', 'b<a' => 'b'}, IGNORE).generate(2).should == 'aaba[a]aa' end end end context "with function a>b" do describe "#generate(x)" do it "should equal 'aaaaaaab' at zero iteration" do Grammar.new('aaaaaaab', {'b' => 'a', 'a>b' => 'b'}).generate(0).should == 'aaaaaaab' end it "should equal 'aaaaaba' after one iteration" do Grammar.new('aaaaaab', {'b' => 'a', 'a>b' => 'b'}).generate(1).should == 'aaaaaba' end it "should equal 'aaaabaa' after one iteration" do Grammar.new('aaaaaba', {'b' => 'a', 'a>b' => 'b'}).generate(1).should == 'aaaabaa' end it "should equal 'aaaabaa' after two iterations" do Grammar.new('aaaaaab', {'b' => 'a', 'a>b' => 'b'}).generate(2).should == 'aaaabaa' end end end end end
Here is the revised library code:-
###################################### # cs_grammar.rb a context sensitive # 1-L lsystem grammar for # ruby/ruby-processing # by Martin Prout (January 2013) ###################################### ################################## # The grammar class stores rules # in two Hashes, one for cs rules, # one for context free rules. Rules # are filtered on input, and context # is checked using get_rule in production ################################## class Grammar attr_accessor :lh_context attr_reader :axiom, :context, :no_context, :idx, :ignore, :lh_buf def initialize(axiom, rules, ignore = '') @axiom = axiom @no_context = {} @context = {} @ignore = ignore @lh_context = false rules.each_pair do |pair| add_rule pair[0], pair[1] end end def add_rule(pre, rule) if pre.length == 3 if pre[1] == '<' @lh_context = true @context[pre[2]] = pre elsif pre[1] == '>' @context[pre[0]] = pre end @no_context[pre] = rule # key length == 3 elsif pre.length == 1 @no_context[pre] = rule # key length == 1 else print "unrecognized grammar '#{pre}'" end end def generate(repeat = 0) # repeat iteration grammar rules prod = axiom repeat.times do prod = new_production(prod) end return prod end def new_production prod # single iteration grammar rules @idx = 0 @lh_buf = [] if lh_context # create buffer to store lefthand context prod.gsub!(/./) do |ch| if lh_context lh_buf << ch unless ignore.include? ch # store lh context end get_rule(prod, ch) end end def get_rule prod, ch rule = ch # default is return original character as rule (no change) @idx += 1 # increment the index of axiom/production as a side effect if (context.has_key?(ch)) if context[ch][1] == '<' cs_char = context[ch][0] rule = no_context[context[ch]] if cs_char == lh_buf[lh_buf.length - 2] # use context lh sensitive rule elsif context[ch][1] == '>' cs_char = context[ch][2] rule = no_context[context[ch]] if cs_char == get_rh_context(prod[idx .. prod.length]) # use context rh sensitive rule end else rule = no_context[ch] if no_context.has_key?(ch) # context free rule if it exists end return rule end def get_rh_context prod index = 0 if ignore != '' while (ignore.include? prod[index]) index += 1 end end return prod[index] end end
No comments:
Post a Comment