summaryrefslogtreecommitdiff
path: root/tool/lrama/lib/lrama/grammar/parameterizing_rule
diff options
context:
space:
mode:
Diffstat (limited to 'tool/lrama/lib/lrama/grammar/parameterizing_rule')
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb62
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb40
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb24
3 files changed, 126 insertions, 0 deletions
diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb
new file mode 100644
index 0000000000..06f2f1cef7
--- /dev/null
+++ b/tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Lrama
+ class Grammar
+ class ParameterizingRule
+ class Resolver
+ attr_accessor :rules, :created_lhs_list
+
+ def initialize
+ @rules = []
+ @created_lhs_list = []
+ end
+
+ def add_parameterizing_rule(rule)
+ @rules << rule
+ end
+
+ def find_rule(token)
+ select_rules(@rules, token).last
+ end
+
+ def find_inline(token)
+ @rules.reverse.find { |rule| rule.name == token.s_value && rule.is_inline }
+ end
+
+ def created_lhs(lhs_s_value)
+ @created_lhs_list.reverse.find { |created_lhs| created_lhs.s_value == lhs_s_value }
+ end
+
+ def redefined_rules
+ @rules.select { |rule| @rules.count { |r| r.name == rule.name && r.required_parameters_count == rule.required_parameters_count } > 1 }
+ end
+
+ private
+
+ def select_rules(rules, token)
+ rules = select_not_inline_rules(rules)
+ rules = select_rules_by_name(rules, token.rule_name)
+ rules = rules.select { |rule| rule.required_parameters_count == token.args_count }
+ if rules.empty?
+ raise "Invalid number of arguments. `#{token.rule_name}`"
+ else
+ rules
+ end
+ end
+
+ def select_not_inline_rules(rules)
+ rules.select { |rule| !rule.is_inline }
+ end
+
+ def select_rules_by_name(rules, rule_name)
+ rules = rules.select { |rule| rule.name == rule_name }
+ if rules.empty?
+ raise "Parameterizing rule does not exist. `#{rule_name}`"
+ else
+ rules
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb
new file mode 100644
index 0000000000..d574841d08
--- /dev/null
+++ b/tool/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Lrama
+ class Grammar
+ class ParameterizingRule
+ class Rhs
+ attr_accessor :symbols, :user_code, :precedence_sym
+
+ def initialize
+ @symbols = []
+ @user_code = nil
+ @precedence_sym = nil
+ end
+
+ def resolve_user_code(bindings)
+ return unless user_code
+
+ resolved = Lexer::Token::UserCode.new(s_value: user_code.s_value, location: user_code.location)
+ var_to_arg = {}
+ symbols.each do |sym|
+ resolved_sym = bindings.resolve_symbol(sym)
+ if resolved_sym != sym
+ var_to_arg[sym.s_value] = resolved_sym.s_value
+ end
+ end
+
+ var_to_arg.each do |var, arg|
+ resolved.references.each do |ref|
+ if ref.name == var
+ ref.name = arg
+ end
+ end
+ end
+
+ return resolved
+ end
+ end
+ end
+ end
+end
diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb
new file mode 100644
index 0000000000..cc200d2fb6
--- /dev/null
+++ b/tool/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Lrama
+ class Grammar
+ class ParameterizingRule
+ class Rule
+ attr_reader :name, :parameters, :rhs_list, :required_parameters_count, :tag, :is_inline
+
+ def initialize(name, parameters, rhs_list, tag: nil, is_inline: false)
+ @name = name
+ @parameters = parameters
+ @rhs_list = rhs_list
+ @tag = tag
+ @is_inline = is_inline
+ @required_parameters_count = parameters.count
+ end
+
+ def to_s
+ "#{@name}(#{@parameters.map(&:s_value).join(', ')})"
+ end
+ end
+ end
+ end
+end