From 280b749e38cd5c3bcf598b3493563f92fdf7efb7 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 27 Sep 2021 21:29:44 -0400 Subject: [PATCH] Track Rule IDs --- lib/imbecile.rb | 8 ++++---- lib/imbecile/parser.rb | 13 ++++--------- lib/imbecile/parser/item.rb | 34 +++++++++++++++------------------- lib/imbecile/rule.rb | 32 ++++++++++++++++++++++++++------ 4 files changed, 49 insertions(+), 38 deletions(-) diff --git a/lib/imbecile.rb b/lib/imbecile.rb index 3443fcf..6fdf234 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] ||= [] - @rules[rule_name] << Rule.new(rule_name, components, code) + @rules[rule_name] ||= Rule.new(rule_name, @rules.size) + @rules[rule_name].add_pattern(components, code) else if input.size > 25 input = input.slice(0..20) + "..." @@ -106,8 +106,8 @@ class Imbecile unless @rules["Start"] raise Error.new("Start rule not found") end - @rules.each do |rule_name, rules| - rules.each do |rule| + @rules.each do |rule_name, rule| + rule.patterns.each do |rule| rule.components.map! do |component| if token_names[component] token_names[component] diff --git a/lib/imbecile/parser.rb b/lib/imbecile/parser.rb index 61f4046..d960011 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 = {} - start_items = rules["Start"].map do |rule| - rule.components << @token_eof - Item.new(rule, 0) + start_items = rules["Start"].patterns.map do |pattern| + pattern.components << @token_eof + Item.new(pattern, 0) end eval_item_sets = Set.new eval_item_sets << ItemSet.new(start_items) @@ -40,12 +40,7 @@ class Imbecile end puts item_set item_set.follow_item_set.each do |follow_symbol, follow_item_set| - if follow_symbol.is_a?(Token) - name = follow_symbol.name - else - name = follow_symbol[0].name - end - puts " #{name} => #{follow_item_set.id}" + puts " #{follow_symbol.name} => #{follow_item_set.id}" end puts end diff --git a/lib/imbecile/parser/item.rb b/lib/imbecile/parser/item.rb index b1ea61c..6ca5e00 100644 --- a/lib/imbecile/parser/item.rb +++ b/lib/imbecile/parser/item.rb @@ -3,24 +3,24 @@ class Imbecile class Item - attr_reader :rule + attr_reader :pattern attr_reader :position - def initialize(rule, position) - @rule = rule + def initialize(pattern, position) + @pattern = pattern @position = position end def next_component - @rule.components[@position] + @pattern.components[@position] end def hash - [@rule, @position].hash + [@pattern, @position].hash end def ==(other) - @rule == other.rule && @position == other.position + @pattern == other.pattern && @position == other.position end def eql?(other) @@ -28,9 +28,9 @@ class Imbecile end def closed_items - if @rule.components[@position].is_a?(Array) - @rule.components[@position].map do |rule| - Item.new(rule, 0) + if @pattern.components[@position].is_a?(Rule) + @pattern.components[@position].patterns.map do |pattern| + Item.new(pattern, 0) end else [] @@ -38,7 +38,7 @@ class Imbecile end def follow_symbol - @rule.components[@position] + @pattern.components[@position] end def followed_by?(symbol) @@ -46,25 +46,21 @@ class Imbecile end def next_position - Item.new(@rule, @position + 1) + Item.new(@pattern, @position + 1) end def to_s parts = [] - @rule.components.each_with_index do |symbol, index| + @pattern.components.each_with_index do |symbol, index| if @position == index parts << "." end - if symbol.is_a?(Token) - parts << symbol.name - else - parts << symbol[0].name - end + parts << symbol.name end - if @position == @rule.components.size + if @position == @pattern.components.size parts << "." end - "#{@rule.name} -> #{parts.join(" ")}" + "#{@pattern.rule.name} -> #{parts.join(" ")}" end end diff --git a/lib/imbecile/rule.rb b/lib/imbecile/rule.rb index 42d1be2..f0e2687 100644 --- a/lib/imbecile/rule.rb +++ b/lib/imbecile/rule.rb @@ -2,16 +2,36 @@ class Imbecile class Rule + class Pattern + + attr_reader :rule + + attr_reader :components + + attr_reader :code + + def initialize(rule, components, code) + @rule = rule + @components = components + @code = code + end + + end + + attr_reader :id + attr_reader :name - attr_reader :components + attr_reader :patterns - attr_reader :code - - def initialize(name, components, code) + def initialize(name, id) @name = name - @components = components - @code = code + @id = id + @patterns = [] + end + + def add_pattern(components, code) + @patterns << Pattern.new(self, components, code) end end