diff --git a/lib/imbecile.rb b/lib/imbecile.rb index fb810f6..3443fcf 100644 --- a/lib/imbecile.rb +++ b/lib/imbecile.rb @@ -81,8 +81,8 @@ class Imbecile elsif input.slice!(/\A(\S+)\s*:\s*\[(.*?)\] <<\n(.*?)^>>\n/m) rule_name, components, code = $1, $2, $3 components = components.strip.split(/\s+/) - @rules[rule_name] ||= Rule.new(rule_name) - @rules[rule_name].add_pattern(components, code) + @rules[rule_name] ||= [] + @rules[rule_name] << Rule.new(rule_name, components, code) else if input.size > 25 input = input.slice(0..20) + "..." @@ -106,9 +106,9 @@ class Imbecile unless @rules["Start"] raise Error.new("Start rule not found") end - @rules.each do |rule_name, rule| - rule.patterns.each do |pattern| - pattern.components.map! do |component| + @rules.each do |rule_name, rules| + rules.each do |rule| + rule.components.map! do |component| if token_names[component] token_names[component] elsif @rules[component] diff --git a/lib/imbecile/parser.rb b/lib/imbecile/parser.rb index fefcfa7..6bb8de9 100644 --- a/lib/imbecile/parser.rb +++ b/lib/imbecile/parser.rb @@ -6,9 +6,9 @@ class Imbecile token_eof = Token.new("$", nil, TOKEN_EOF) @item_sets = [] item_sets_set = Set.new - start_items = rules["Start"].patterns.map do |pattern| - pattern.components << token_eof - Item.new(pattern, 0) + start_items = rules["Start"].map do |rule| + rule.components << token_eof + Item.new(rule, 0) end eval_item_sets = Set.new eval_item_sets << ItemSet.new(start_items) diff --git a/lib/imbecile/parser/item.rb b/lib/imbecile/parser/item.rb index 8559c1d..b1ea61c 100644 --- a/lib/imbecile/parser/item.rb +++ b/lib/imbecile/parser/item.rb @@ -3,24 +3,24 @@ class Imbecile class Item - attr_reader :pattern + attr_reader :rule attr_reader :position - def initialize(pattern, position) - @pattern = pattern + def initialize(rule, position) + @rule = rule @position = position end def next_component - @pattern.components[@position] + @rule.components[@position] end def hash - [@pattern, @position].hash + [@rule, @position].hash end def ==(other) - @pattern == other.pattern && @position == other.position + @rule == other.rule && @position == other.position end def eql?(other) @@ -28,9 +28,9 @@ class Imbecile end def closed_items - if @pattern.components[@position].is_a?(Rule) - @pattern.components[@position].patterns.map do |pattern| - Item.new(pattern, 0) + if @rule.components[@position].is_a?(Array) + @rule.components[@position].map do |rule| + Item.new(rule, 0) end else [] @@ -38,7 +38,7 @@ class Imbecile end def follow_symbol - @pattern.components[@position] + @rule.components[@position] end def followed_by?(symbol) @@ -46,21 +46,25 @@ class Imbecile end def next_position - Item.new(@pattern, @position + 1) + Item.new(@rule, @position + 1) end def to_s parts = [] - @pattern.components.each_with_index do |symbol, index| + @rule.components.each_with_index do |symbol, index| if @position == index parts << "." end - parts << symbol.name + if symbol.is_a?(Token) + parts << symbol.name + else + parts << symbol[0].name + end end - if @position == @pattern.components.size + if @position == @rule.components.size parts << "." end - parts.join(" ") + "#{@rule.name} -> #{parts.join(" ")}" end end diff --git a/lib/imbecile/rule.rb b/lib/imbecile/rule.rb index 4398248..42d1be2 100644 --- a/lib/imbecile/rule.rb +++ b/lib/imbecile/rule.rb @@ -2,30 +2,16 @@ class Imbecile class Rule - class Pattern - - attr_reader :components - - attr_reader :code - - def initialize(components, code) - @components = components - @code = code - end - - end - attr_reader :name - attr_reader :patterns + attr_reader :components - def initialize(name) + attr_reader :code + + def initialize(name, components, code) @name = name - @patterns = [] - end - - def add_pattern(components, code) - @patterns << Pattern.new(components, code) + @components = components + @code = code end end