diff --git a/lib/imbecile.rb b/lib/imbecile.rb index bff56f8..234701c 100644 --- a/lib/imbecile.rb +++ b/lib/imbecile.rb @@ -8,6 +8,8 @@ require_relative "imbecile/fa/state/transition" require_relative "imbecile/lexer" require_relative "imbecile/lexer/dfa" require_relative "imbecile/parser" +require_relative "imbecile/parser/item" +require_relative "imbecile/parser/item_set" require_relative "imbecile/regex" require_relative "imbecile/regex/nfa" require_relative "imbecile/regex/unit" diff --git a/lib/imbecile/parser.rb b/lib/imbecile/parser.rb index 023b00a..8a1c923 100644 --- a/lib/imbecile/parser.rb +++ b/lib/imbecile/parser.rb @@ -3,6 +3,12 @@ class Imbecile class Parser def initialize(tokens, rules) + start_rules = rules.select {|rule| rule.name == "Start"} + start_items = start_rules.map do |rule| + Item.new(rule, 0) + end + start_item_set = ItemSet.new(start_items) + start_item_set.close! end end diff --git a/lib/imbecile/parser/item.rb b/lib/imbecile/parser/item.rb new file mode 100644 index 0000000..81e8c8a --- /dev/null +++ b/lib/imbecile/parser/item.rb @@ -0,0 +1,33 @@ +class Imbecile + class Parser + + class Item + + attr_reader :rule + attr_reader :position + + def initialize(rule, position) + @rule = rule + @position = position + end + + def next_component + @rule.components[@position] + end + + def hash + [@rule, @position].hash + end + + def ==(other) + @rule == other.rule && @position == other.position + end + + def eql?(other) + self == other + end + + end + + end +end diff --git a/lib/imbecile/parser/item_set.rb b/lib/imbecile/parser/item_set.rb new file mode 100644 index 0000000..bb5f232 --- /dev/null +++ b/lib/imbecile/parser/item_set.rb @@ -0,0 +1,26 @@ +class Imbecile + class Parser + + class ItemSet + + def initialize(items) + @items = Set.new(items) + end + + def close! + eval_items = @items + while eval_items.size > 0 + this_eval_items = eval_items + eval_items = Set.new + this_eval_items.each do |item| + if item.next_component.is_a?(Rule) + end + end + @items += eval_items + end + end + + end + + end +end diff --git a/spec/imbecile/parser/item_spec.rb b/spec/imbecile/parser/item_spec.rb new file mode 100644 index 0000000..aefc461 --- /dev/null +++ b/spec/imbecile/parser/item_spec.rb @@ -0,0 +1,19 @@ +class Imbecile + class Parser + + describe Item do + + it "operates properly with a set" do + rule = Object.new + item1 = Item.new(rule, 2) + item2 = Item.new(rule, 2) + expect(item1).to eq item2 + expect(item1.eql?(item2)).to be_truthy + set = Set.new([item1, item2]) + expect(set.size).to eq 1 + end + + end + + end +end