8 alias_method :to_s, :token
9 alias_method :to_tree, :token
14 other.is_a?(Terminal) and other.token==@token
16 alias_method :==, :eql?
17 alias_method :===, :eql?
21 attr_accessor :i,:j,:category,:contents,:sub
22 def initialize(i,j,category,contents,sub=[])
30 other.is_a? Edge and hash == other.hash
32 alias_method :==, :eql?
33 alias_method :===, :eql?
35 [@i,@j,@category,@contents,@sub].hash
38 "#{active? ? 'A' : 'I'}"+
39 "<#{@i},#{@j},#{@category},[%s],[%s]>" % [@contents.join(', '),
43 unfound and unfound.length != 0
46 @contents[@sub.length..-1]
52 #raise Exception if active?
54 [@category, @sub.map{|e|e.to_tree}]
56 [@category, @contents.map{|e|e.to_tree}]
62 def initialize(grammar,log=Logger.new(STDERR))
71 # Initialise agenda with known words
72 text.each_with_index do |word,n|
74 @grammar.each do |cat,rule|
76 if r == [Terminal.new(word)]
77 agenda << Edge.new(n,n+1,cat,[],[Terminal.new(word)])
84 # Move one from agenda to chart
85 chart << agenda.delete_at(0)
86 # Add to the agenda from edges in the chart
87 new_edges(chart) do |edge|
88 unless agenda.include?(edge) or chart.include?(edge)
89 @log.debug("new_edges adding: #{edge}")
95 @log.debug("agenda: #{edge}")
98 @log.debug("chart: #{edge}")
103 # Return all spanning parses in Array form
104 chart.select do |edge|
105 edge.i == 0 and edge.j == text.length
112 bottom_up(chart) do |edge|
115 fundamental(chart) do |edge|
122 #TODO: is this next line required by the algorithm?
124 @grammar.each do |r,w|
126 if ww[0] == edge.category
127 newedge = Edge.new(edge.i,edge.i,r,ww)
128 @log.debug("bottom_up: via #{edge} found #{newedge}")
136 def fundamental(chart)
139 #TODO: (optimisation)
140 # This could be removed if the chart was split into inactive and active
151 if a.j == i.i and a.nextWord == i.category
152 newedge = Edge.new(a.i,i.j,a.category,a.contents,a.sub+[i])
153 @log.debug("fundamental: via #{a} and #{i} found #{newedge}")
163 log = Logger.new(STDERR)
164 log.level = Logger::DEBUG
165 log.formatter = lambda {|severity,time,progname,msg| "#{severity}: #{msg}\n"}
167 shouldBe = Set.new([["S", [["NP", [["NP", ["time"]], ["NP", ["flies"]]]],
168 ["VP", [["V", ["like"]], ["NP", [["Det", ["an"]], ["NP", ["arrow"]]]]]]]],
169 ["S", [["NP", ["time"]], ["VP", [["V", ["flies"]], ["PP", [["PR", ["like"]],
170 ["NP", [["Det", ["an"]], ["NP", ["arrow"]]]]]]]]]]])
172 grammar = {'S'=>[%w{NP VP}],
175 'NP'=>[[Terminal.new('time')],
176 [Terminal.new('flies')],
177 [Terminal.new('arrow')],
181 'PR'=>[[Terminal.new('like')]],
182 'Det'=>[[Terminal.new('an')]],
183 'V'=>[[Terminal.new('like')],
184 [Terminal.new('flies')]]}
186 p = Parser.new(grammar,log)
187 q = p.parse(%w{time flies like an arrow})
190 puts "Test succeeded!"
191 puts "Output was #{q.inspect}"
194 puts "Should have been #{shouldBe.inspect}"
195 puts "But was actually #{q.inspect}"