From 514e61c6c7caa735334a10e09ec598807e401004 Mon Sep 17 00:00:00 2001 From: ydah Date: Wed, 17 Apr 2024 23:04:48 +0900 Subject: [PATCH] Refactor for parameterizing_rule_resolver --- lib/lrama/grammar.rb | 12 ++++++--- lib/lrama/grammar/rule_builder.rb | 33 +++++++++++++------------ lib/lrama/parser.rb | 4 +-- parser.y | 4 +-- sig/lrama/grammar/rule_builder.rbs | 9 ++++--- spec/lrama/grammar/rule_builder_spec.rb | 6 ++--- 6 files changed, 37 insertions(+), 31 deletions(-) diff --git a/lib/lrama/grammar.rb b/lib/lrama/grammar.rb index 229f757b..dc53bbc1 100644 --- a/lib/lrama/grammar.rb +++ b/lib/lrama/grammar.rb @@ -63,6 +63,10 @@ def initialize(rule_counter) append_special_symbols end + def create_rule_builder(rule_counter, midrule_action_counter) + RuleBuilder.new(rule_counter, midrule_action_counter, @parameterizing_rule_resolver) + end + def add_percent_code(id:, code:) @percent_codes << PercentCode.new(id.s_value, code.s_value) end @@ -256,7 +260,7 @@ def compute_first_set def setup_rules @rule_builders.each do |builder| - builder.setup_rules(@parameterizing_rule_resolver) + builder.setup_rules end end @@ -291,10 +295,10 @@ def append_special_symbols end def resolve_inline_rules - while @rule_builders.any? {|r| r.has_inline_rules?(@parameterizing_rule_resolver) } do + while @rule_builders.any? {|r| r.has_inline_rules? } do @rule_builders.map! do |builder| - if builder.has_inline_rules?(@parameterizing_rule_resolver) - builder.resolve_inline_rules(@parameterizing_rule_resolver) + if builder.has_inline_rules? + builder.resolve_inline_rules else builder end diff --git a/lib/lrama/grammar/rule_builder.rb b/lib/lrama/grammar/rule_builder.rb index 29001d85..c16db450 100644 --- a/lib/lrama/grammar/rule_builder.rb +++ b/lib/lrama/grammar/rule_builder.rb @@ -4,9 +4,10 @@ class RuleBuilder attr_accessor :lhs, :line attr_reader :lhs_tag, :rhs, :user_code, :precedence_sym - def initialize(rule_counter, midrule_action_counter, position_in_original_rule_rhs = nil, lhs_tag: nil, skip_preprocess_references: false) + def initialize(rule_counter, midrule_action_counter, parameterizing_rule_resolver, position_in_original_rule_rhs = nil, lhs_tag: nil, skip_preprocess_references: false) @rule_counter = rule_counter @midrule_action_counter = midrule_action_counter + @parameterizing_rule_resolver = parameterizing_rule_resolver @position_in_original_rule_rhs = position_in_original_rule_rhs @skip_preprocess_references = skip_preprocess_references @@ -53,9 +54,9 @@ def complete_input freeze_rhs end - def setup_rules(parameterizing_rule_resolver) + def setup_rules preprocess_references unless @skip_preprocess_references - process_rhs(parameterizing_rule_resolver) + process_rhs build_rules end @@ -63,16 +64,16 @@ def rules @parameterizing_rules + @midrule_action_rules + @rules end - def has_inline_rules?(parameterizing_rule_resolver) - rhs.any? { |token| parameterizing_rule_resolver.find_inline(token) } + def has_inline_rules? + rhs.any? { |token| @parameterizing_rule_resolver.find_inline(token) } end - def resolve_inline_rules(parameterizing_rule_resolver) + def resolve_inline_rules resolved_builders = [] rhs.each_with_index do |token, i| - if inline_rule = parameterizing_rule_resolver.find_inline(token) + if inline_rule = @parameterizing_rule_resolver.find_inline(token) inline_rule.rhs_list.each do |inline_rhs| - rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, lhs_tag: lhs_tag) + rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, @parameterizing_rule_resolver, lhs_tag: lhs_tag) resolve_inline_rhs(rule_builder, inline_rhs, i) rule_builder.lhs = lhs rule_builder.line = line @@ -117,7 +118,7 @@ def build_rules # rhs is a mixture of variety type of tokens like `Ident`, `InstantiateRule`, `UserCode` and so on. # `#process_rhs` replaces some kind of tokens to `Ident` so that all `@replaced_rhs` are `Ident` or `Char`. - def process_rhs(parameterizing_rule_resolver) + def process_rhs return if @replaced_rhs @replaced_rhs = [] @@ -129,26 +130,26 @@ def process_rhs(parameterizing_rule_resolver) when Lrama::Lexer::Token::Ident @replaced_rhs << token when Lrama::Lexer::Token::InstantiateRule - parameterizing_rule = parameterizing_rule_resolver.find_rule(token) + parameterizing_rule = @parameterizing_rule_resolver.find_rule(token) raise "Unexpected token. #{token}" unless parameterizing_rule bindings = Binding.new(parameterizing_rule, token.args) lhs_s_value = lhs_s_value(token, bindings) - if (created_lhs = parameterizing_rule_resolver.created_lhs(lhs_s_value)) + if (created_lhs = @parameterizing_rule_resolver.created_lhs(lhs_s_value)) @replaced_rhs << created_lhs else lhs_token = Lrama::Lexer::Token::Ident.new(s_value: lhs_s_value, location: token.location) @replaced_rhs << lhs_token - parameterizing_rule_resolver.created_lhs_list << lhs_token + @parameterizing_rule_resolver.created_lhs_list << lhs_token parameterizing_rule.rhs_list.each do |r| - rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, lhs_tag: token.lhs_tag, skip_preprocess_references: true) + rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, @parameterizing_rule_resolver, lhs_tag: token.lhs_tag, skip_preprocess_references: true) rule_builder.lhs = lhs_token r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) } rule_builder.line = line rule_builder.precedence_sym = r.precedence_sym rule_builder.user_code = r.user_code rule_builder.complete_input - rule_builder.setup_rules(parameterizing_rule_resolver) + rule_builder.setup_rules @rule_builders_for_parameterizing_rules << rule_builder end end @@ -158,11 +159,11 @@ def process_rhs(parameterizing_rule_resolver) new_token = Lrama::Lexer::Token::Ident.new(s_value: prefix + @midrule_action_counter.increment.to_s) @replaced_rhs << new_token - rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: tag, skip_preprocess_references: true) + rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, @parameterizing_rule_resolver, i, lhs_tag: tag, skip_preprocess_references: true) rule_builder.lhs = new_token rule_builder.user_code = token rule_builder.complete_input - rule_builder.setup_rules(parameterizing_rule_resolver) + rule_builder.setup_rules @rule_builders_for_derived_rules << rule_builder else diff --git a/lib/lrama/parser.rb b/lib/lrama/parser.rb index 45da0fea..7c190716 100644 --- a/lib/lrama/parser.rb +++ b/lib/lrama/parser.rb @@ -2011,7 +2011,7 @@ def _reduce_102(val, _values, result) module_eval(<<'.,.,', 'parser.y', 427) def _reduce_104(val, _values, result) reset_precs - result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) + result = @grammar.create_rule_builder(@rule_counter, @midrule_action_counter) result end @@ -2020,7 +2020,7 @@ def _reduce_104(val, _values, result) module_eval(<<'.,.,', 'parser.y', 432) def _reduce_105(val, _values, result) reset_precs - result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) + result = @grammar.create_rule_builder(@rule_counter, @midrule_action_counter) result end diff --git a/parser.y b/parser.y index 878e7a59..ff8df3d7 100644 --- a/parser.y +++ b/parser.y @@ -426,12 +426,12 @@ rule rhs: /* empty */ { reset_precs - result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) + result = @grammar.create_rule_builder(@rule_counter, @midrule_action_counter) } | "%empty" { reset_precs - result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) + result = @grammar.create_rule_builder(@rule_counter, @midrule_action_counter) } | rhs symbol named_ref_opt { diff --git a/sig/lrama/grammar/rule_builder.rbs b/sig/lrama/grammar/rule_builder.rbs index 7f210b76..5efed93c 100644 --- a/sig/lrama/grammar/rule_builder.rbs +++ b/sig/lrama/grammar/rule_builder.rbs @@ -10,6 +10,7 @@ module Lrama @rule_counter: Counter @midrule_action_counter: Counter + @parameterizing_rule_resolver: Grammar::ParameterizingRule::Resolver @position_in_original_rule_rhs: Integer? @skip_preprocess_references: bool @user_code: Lexer::Token::UserCode? @@ -20,12 +21,12 @@ module Lrama @parameterizing_rules: Array[Rule] @midrule_action_rules: Array[Rule] - def initialize: (Counter rule_counter, Counter midrule_action_counter, ?Integer position_in_original_rule_rhs, ?lhs_tag: Lexer::Token::Tag?, ?skip_preprocess_references: bool) -> void + def initialize: (Counter rule_counter, Counter midrule_action_counter, Grammar::ParameterizingRule::Resolver parameterizing_rule_resolver, ?Integer position_in_original_rule_rhs, ?lhs_tag: Lexer::Token::Tag?, ?skip_preprocess_references: bool) -> void def add_rhs: (Lexer::Token rhs) -> void def user_code=: (Lexer::Token::UserCode? user_code) -> void def precedence_sym=: (Lexer::Token? precedence_sym) -> void def complete_input: () -> void - def setup_rules: (Grammar::ParameterizingRule::Resolver parameterizing_rule_resolver) -> void + def setup_rules: () -> void def rules: () -> Array[Rule] private @@ -33,9 +34,9 @@ module Lrama def freeze_rhs: () -> void def preprocess_references: () -> void def build_rules: () -> void - def process_rhs: (Grammar::ParameterizingRule::Resolver parameterizing_rule_resolver) -> void + def process_rhs: () -> void def lhs_s_value: (Lexer::Token::InstantiateRule token, Grammar::Binding bindings) -> String - def resolve_inline: (Grammar::ParameterizingRule::Resolver parameterizing_rule_resolver) -> void + def resolve_inline: () -> void def resolve_inline_rhs: (RuleBuilder rule_builder, Grammar::ParameterizingRule::Rhs inline_rhs, Integer index) -> void def replace_inline_user_code: (Grammar::ParameterizingRule::Rhs inline_rhs, Integer index) -> Lexer::Token::UserCode? def numberize_references: () -> void diff --git a/spec/lrama/grammar/rule_builder_spec.rb b/spec/lrama/grammar/rule_builder_spec.rb index 39b190be..a2ba733a 100644 --- a/spec/lrama/grammar/rule_builder_spec.rb +++ b/spec/lrama/grammar/rule_builder_spec.rb @@ -1,7 +1,7 @@ RSpec.describe Lrama::Grammar::RuleBuilder do let(:rule_counter) { Lrama::Grammar::Counter.new(1) } let(:midrule_action_counter) { Lrama::Grammar::Counter.new(1) } - let(:rule_builder) { Lrama::Grammar::RuleBuilder.new(rule_counter, midrule_action_counter) } + let(:rule_builder) { Lrama::Grammar::RuleBuilder.new(rule_counter, midrule_action_counter, Lrama::Grammar::ParameterizingRule::Resolver.new) } let(:path) { "parse.y" } describe "#add_rhs" do @@ -464,7 +464,7 @@ class : keyword_class tSTRING keyword_end { $classes = $1; } rule_builder.add_rhs(token_6) rule_builder.user_code = token_7 rule_builder.complete_input - rule_builder.setup_rules(Lrama::Grammar::ParameterizingRule::Resolver.new) + rule_builder.setup_rules rules = rule_builder.rules midrule_1 = rules.find {|rule| rule._lhs.s_value == "@1"} @@ -501,7 +501,7 @@ class : keyword_class tSTRING keyword_end { $classes = $1; } rule_builder.add_rhs(token_6) rule_builder.user_code = token_7 rule_builder.complete_input - rule_builder.setup_rules(Lrama::Grammar::ParameterizingRule::Resolver.new) + rule_builder.setup_rules tokens = rule_builder.instance_variable_get(:@replaced_rhs)