summaryrefslogtreecommitdiff
path: root/intersect.rb
diff options
context:
space:
mode:
Diffstat (limited to 'intersect.rb')
-rw-r--r--intersect.rb174
1 files changed, 174 insertions, 0 deletions
diff --git a/intersect.rb b/intersect.rb
new file mode 100644
index 0000000..8a583da
--- /dev/null
+++ b/intersect.rb
@@ -0,0 +1,174 @@
+#!/usr/bin/env ruby
+
+require_relative './grammar.rb'
+
+# interescts a WFSA (WFST) with a WSCFG to produce a hypergraph
+
+
+
+class Chart
+ attr_accessor :m
+
+ def initialize input
+ @m = []
+ (input.size+1).times {
+ _ = []
+ (input.size+1).times { _ << [] }
+ @m << _
+ }
+ end
+
+ def at span
+ return @m[span.left][span.right]
+ end
+
+ def at i,j
+ return @m[i][j]
+ end
+end
+
+class Item < Rule
+ attr_accessor :lhs, :rhs, :span, :dot
+
+ def initialize rule, dot=-1
+ @lhs = rule.lhs.dup
+ @rhs = rule.rhs.dup
+ @span = Span.new rule.span.left, rule.span.right
+ @dot = dot
+ if rule.class==Item
+ @dot = rule.dot
+ end
+ end
+
+ def to_s
+ "#{lhs} -> #{rhs.map{|i|i.to_s}.insert(@dot,'*').join ' '} (dot:#{@dot}) (a:#{arity}) (#{@span.left}, #{@span.right})"
+ end
+end
+
+
+
+#def shift
+#end
+#def reduce
+#end
+#def init
+ #axioms,goals etc
+#end
+#def parse
+#end
+
+
+g = Grammar.new 'grammar'
+input = "ich sah ein kleines haus".split.map { |i| Terminal.new i }
+#start = NonTerminal.new 'S'
+
+passive_chart = Chart.new input
+active_chart = Chart.new input
+
+
+
+# 1st row: arity0 rules
+unary_rules = g.rules.reject { |r| r.arity>0 }
+input.each_with_index { |t,j|
+ unary_rules.each { |r|
+ if r.rhs.first.w == t.w
+ passive_chart.at(j,j+1) << Item.new(r)
+ passive_chart.at(j,j+1).last.span.left = j
+ passive_chart.at(j,j+1).last.span.right = j+1
+ passive_chart.at(j,j+1).last.dot = 1
+ end
+ }
+}
+
+
+
+# pre-fill active chart with non 0arity rules starting with a (single(!)) T
+g.rules.reject{|r| r.rhs[0].class==NonTerminal||r.arity==0}.each {|r|
+ input.each_with_index { |i,j|
+ if i.w==r.rhs.first.w
+ (j+2).upto(input.size) { |k| # no empty NT!
+ active_chart.at(j,k) << Item.new(r)
+ active_chart.at(j,k).last.span.left = j
+ active_chart.at(j,k).last.span.right = k #j+1 # k
+ active_chart.at(j,k).last.dot = 1
+ }
+ end
+ }
+}
+# pre-fill active chart
+s = g.rules.reject { |r| r.rhs.first.class!=NonTerminal}#.reject{|r| r.lhs.sym == 'S'}
+(input.size).times { |k|
+ 0.upto(input.size-(k+2)) { |i|
+ s.each { |r|
+ active_chart.at(i,i+k+2) << Item.new(r)
+ active_chart.at(i,i+k+2).last.span.left = i
+ active_chart.at(i,i+k+2).last.span.right = i+k+2
+ active_chart.at(i,i+k+2).last.dot = 0
+ }
+ }
+}
+
+
+
+# parse
+puts "parse"
+def visit i, j, sz, active_chart, passive_chart, g, input
+ puts "| #{i},#{j}"
+
+ # SCAN
+ active_chart.at(i,j).each { |item|
+ if item.rhs[item.dot].class == Terminal
+ if item.rhs[item.dot].w == input[item.span.left+item.dot].w
+ item.dot += 1
+ if item.dot == item.rhs.size
+ passive_chart.at(i,j) << Item.new(item)
+ #passive_chart.at(i,j).last.span.right = item.span.left+item.dot
+ end
+ end
+ end
+ }
+
+ 1.upto(sz) { |span|
+ break if span==(j-i)
+ i.upto(j-span) { |k|
+ puts " #{k},#{k+span} (##{span})"
+ # COMPLETE
+ active_chart.at(i,j).each { |active_item|
+ passive_chart.at(k, k+span).each { |passive_item|
+ if active_item.rhs[active_item.dot].class==NonTerminal && passive_item.lhs.sym == active_item.rhs[active_item.dot].sym
+ active_item.span.right = passive_item.span.right if passive_item.span.right > active_item.span.right
+ active_item.dot += 1
+ if active_item.dot == active_item.rhs.size
+ passive_chart.at(i,j) << Item.new(active_item)
+ end
+ end
+ }
+ }
+ }
+
+ # SCAN
+ active_chart.at(i,j).each { |item|
+ if item.rhs[item.dot].class == Terminal
+ if item.rhs[item.dot].w == input[item.span.left+item.dot].w
+ item.dot += 1
+ if item.dot == item.rhs.size
+ passive_chart.at(i,j) << Item.new(item)
+ end
+ end
+ end
+ }
+
+ }
+end
+
+(input.size).times { |k|
+ 0.upto(input.size-(k+2)) { |i|
+ visit i, i+k+2, input.size, active_chart, passive_chart, g, input
+ }
+}
+puts "---"
+
+active_chart.at(0,5).each { |item|
+ puts item.to_s
+}
+