From 6026bf1514c68c985736d091787b3f3c811ea279 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Sun, 29 Aug 2021 09:41:00 -0400 Subject: [PATCH] Start building following item sets --- lib/imbecile/parser.rb | 12 ++++++++++- lib/imbecile/parser/item.rb | 26 ++++++++++++++++++++++++ lib/imbecile/parser/item_set.rb | 35 +++++++++++++++++++++++++++++++++ spec/imbecile_spec.rb | 6 +++++- 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/lib/imbecile/parser.rb b/lib/imbecile/parser.rb index 97789a2..2d3c90d 100644 --- a/lib/imbecile/parser.rb +++ b/lib/imbecile/parser.rb @@ -3,11 +3,21 @@ class Imbecile class Parser def initialize(tokens, rules) + @item_sets = [] + item_sets_set = Set.new start_items = rules["Start"].patterns.map do |pattern| Item.new(pattern, 0) end start_item_set = ItemSet.new(start_items) - start_item_set.close! + + puts "Start item set:" + puts start_item_set + start_item_set.follow_symbols.each do |follow_symbol| + follow_set = start_item_set.follow_set(follow_symbol) + puts + puts "follow set:" + puts follow_set + end end end diff --git a/lib/imbecile/parser/item.rb b/lib/imbecile/parser/item.rb index cf10336..8559c1d 100644 --- a/lib/imbecile/parser/item.rb +++ b/lib/imbecile/parser/item.rb @@ -37,6 +37,32 @@ class Imbecile end end + def follow_symbol + @pattern.components[@position] + end + + def followed_by?(symbol) + follow_symbol == symbol + end + + def next_position + Item.new(@pattern, @position + 1) + end + + def to_s + parts = [] + @pattern.components.each_with_index do |symbol, index| + if @position == index + parts << "." + end + parts << symbol.name + end + if @position == @pattern.components.size + parts << "." + end + parts.join(" ") + end + end end diff --git a/lib/imbecile/parser/item_set.rb b/lib/imbecile/parser/item_set.rb index b77d4dc..8bc337d 100644 --- a/lib/imbecile/parser/item_set.rb +++ b/lib/imbecile/parser/item_set.rb @@ -3,10 +3,39 @@ class Imbecile class ItemSet + attr_reader :items + def initialize(items) @items = Set.new(items) + close! end + def follow_symbols + Set.new(@items.map(&:follow_symbol)) + end + + def follow_set(symbol) + ItemSet.new(items_followed_by(symbol).map(&:next_position)) + end + + def hash + @items.hash + end + + def ==(other) + @items.eql?(other.items) + end + + def eql?(other) + self == other + end + + def to_s + @items.map(&:to_s).join("\n") + end + + private + def close! eval_items = @items while eval_items.size > 0 @@ -19,6 +48,12 @@ class Imbecile end end + def items_followed_by(symbol) + @items.select do |item| + item.followed_by?(symbol) + end + end + end end diff --git a/spec/imbecile_spec.rb b/spec/imbecile_spec.rb index 7424286..0bfa784 100644 --- a/spec/imbecile_spec.rb +++ b/spec/imbecile_spec.rb @@ -31,7 +31,11 @@ token int \\d+ token plus \\+ token times \\* drop \\s+ -Start: [] << +Start: [Foo] << +>> +Foo: [int] << +>> +Foo: [plus] << >> EOF build_parser