summaryrefslogtreecommitdiff
path: root/algorithms/shift_reduce_parser.rb
diff options
context:
space:
mode:
authorPatrick Simianer <p@simianer.de>2014-10-10 14:20:59 +0100
committerPatrick Simianer <p@simianer.de>2014-10-10 14:20:59 +0100
commitc0ece722bd7775af14c7f2ec18dcd1fd138607cb (patch)
treefab93a5d48d89c9e3c7473a1ca5aafe7b3bcaeed /algorithms/shift_reduce_parser.rb
parentde54ca7c31487a33fa8148159e9b3dea96a9dd4c (diff)
algorithms: shift reduce dependency parsing
Diffstat (limited to 'algorithms/shift_reduce_parser.rb')
-rwxr-xr-xalgorithms/shift_reduce_parser.rb101
1 files changed, 101 insertions, 0 deletions
diff --git a/algorithms/shift_reduce_parser.rb b/algorithms/shift_reduce_parser.rb
new file mode 100755
index 0000000..948d8c1
--- /dev/null
+++ b/algorithms/shift_reduce_parser.rb
@@ -0,0 +1,101 @@
+#!/usr/bin/env ruby
+
+
+class Item
+ attr_accessor :word, :type, :link
+ def initialize word, type
+ @word = word
+ @type = type
+ @link = nil
+ end
+end
+
+class MockShiftReduceParser
+ attr_accessor :state
+
+ def initialize
+ @state = nil
+
+ @a = {}
+ @a[nil] = {}
+ @a[nil][nil] = 'S'
+ @a[nil]['f'] = 'S'
+ @a[nil]['l'] = 'S'
+ @a[nil]['r'] = 'illegal'
+
+ @a['f'] = {}
+ @a['f']['f'] = 'S' # FIXME conflict
+ @a['f']['l'] = 'S'
+ @a['f']['r'] = 'R'
+
+ @a['l'] = {}
+ @a['l']['f'] = 'L'
+ @a['l']['l'] = 'S'
+ @a['l']['r'] = 'illegal'
+
+ @a['r'] = {}
+ @a['r']['f'] = 'illegal'
+ @a['r']['l'] = 'illegal'
+ @a['r']['r'] = 'illegal'
+ end
+
+ def advance type
+ if !@state
+ @state = type
+ puts "-/- -> S -> #{@state}"
+ return
+ end
+ action = @a[@state][type]
+ prev_state = @state
+ if action == 'S'
+ @state = type
+ elsif action == 'L' or action == 'R'
+ @state = 'f'
+ end
+ puts "#{prev_state}/#{type} -> #{action} -> #{@state}"
+
+ return action
+ end
+end
+
+
+parser = MockShiftReduceParser.new
+
+items = []
+head = nil
+stack = []
+
+while line = STDIN.gets
+ word, type = line.split
+ item = Item.new word, type
+ items << item
+ stack << item
+
+ head = item if !head
+
+ action = parser.advance item.type
+ if action == "S"
+ head = item
+ elsif action == "R"
+ _ = stack.pop
+ _.link = head
+ elsif action == "L"
+ head = item
+ puts stack.size
+ del = []
+ stack.each_with_index { |i,j|
+ if i.type == 'l'
+ i.link = head
+ del << j
+ end
+ }
+ del.reverse.each { |d| stack.delete_at(d) }
+ puts stack.size
+ end
+end
+
+stack.each { |i| i.link = head }
+
+puts "---"
+items.each { |j| if j.link then puts "#{j.word} #{j.link.word}" else puts "#{j.word} ?" end }
+