Skip to content

Commit

Permalink
Lazy initialization of RuleAction
Browse files Browse the repository at this point in the history
RuleAction needs relative position of the rule (the nterm)
when it's a midrule action.
Currently the position is managed by `Reference#position_in_rhs`
but it will be moved to Rule.
This is a preparation for the chagne.
  • Loading branch information
yui-knk committed Nov 5, 2023
1 parent 0eb8095 commit 6726470
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 92 deletions.
35 changes: 17 additions & 18 deletions lib/lrama/grammar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ def normalize_rules
accept = find_symbol_by_s_value!("$accept")
eof = find_symbol_by_number!(0)
lineno = @_rules.first ? @_rules.first[2] : 0
@rules << Rule.new(id: @rules.count, lhs: accept, rhs: [@_rules.first[0], eof], code: nil, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: accept, rhs: [@_rules.first[0], eof], token_code: nil, lineno: lineno)

extracted_action_number = 1 # @n as nterm

Expand Down Expand Up @@ -467,15 +467,14 @@ def normalize_rules
# Extract actions in the middle of RHS
# into new rules.
a.each do |new_token, code|
@rules << Rule.new(id: @rules.count, lhs: new_token, rhs: [], code: Code::RuleAction.new(type: :rule_action, token_code: code), lineno: code.line)
@rules << Rule.new(id: @rules.count, lhs: new_token, rhs: [], token_code: code, lineno: code.line)
end

c = code ? Code::RuleAction.new(type: :rule_action, token_code: code) : nil
# Expand Parameterizing rules
if rhs2.any? {|r| r.is_a?(Lrama::Lexer::Token::Parameterizing) }
expand_parameterizing_rules(lhs, rhs2, c, precedence_sym, lineno)
expand_parameterizing_rules(lhs, rhs2, code, precedence_sym, lineno)
else
@rules << Rule.new(id: @rules.count, lhs: lhs, rhs: rhs2, code: c, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: lhs, rhs: rhs2, token_code: code, precedence_sym: precedence_sym, lineno: lineno)
end
add_nterm(id: lhs)
a.each do |new_token, _|
Expand All @@ -489,21 +488,21 @@ def expand_parameterizing_rules(lhs, rhs, code, precedence_sym, lineno)
if rhs.any? {|r| r.is_a?(Lrama::Lexer::Token::Parameterizing) && r.option? }
option_token = Lrama::Lexer::Token::Ident.new(s_value: "option_#{rhs[0].s_value}")
add_term(id: option_token)
@rules << Rule.new(id: @rules.count, lhs: lhs, rhs: [option_token], code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: option_token, rhs: [], code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: option_token, rhs: [token], code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: lhs, rhs: [option_token], token_code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: option_token, rhs: [], token_code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: option_token, rhs: [token], token_code: code, precedence_sym: precedence_sym, lineno: lineno)
elsif rhs.any? {|r| r.is_a?(Lrama::Lexer::Token::Parameterizing) && r.nonempty_list? }
nonempty_list_token = Lrama::Lexer::Token::Ident.new(s_value: "nonempty_list_#{rhs[0].s_value}")
add_term(id: nonempty_list_token)
@rules << Rule.new(id: @rules.count, lhs: lhs, rhs: [nonempty_list_token], code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: nonempty_list_token, rhs: [token], code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: nonempty_list_token, rhs: [nonempty_list_token, token], code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: lhs, rhs: [nonempty_list_token], token_code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: nonempty_list_token, rhs: [token], token_code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: nonempty_list_token, rhs: [nonempty_list_token, token], token_code: code, precedence_sym: precedence_sym, lineno: lineno)
elsif rhs.any? {|r| r.is_a?(Lrama::Lexer::Token::Parameterizing) && r.list? }
list_token = Lrama::Lexer::Token::Ident.new(s_value: "list_#{rhs[0].s_value}")
add_term(id: list_token)
@rules << Rule.new(id: @rules.count, lhs: lhs, rhs: [list_token], code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: list_token, rhs: [], code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: list_token, rhs: [list_token, token], code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: lhs, rhs: [list_token], token_code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: list_token, rhs: [], token_code: code, precedence_sym: precedence_sym, lineno: lineno)
@rules << Rule.new(id: @rules.count, lhs: list_token, rhs: [list_token, token], token_code: code, precedence_sym: precedence_sym, lineno: lineno)
end
end

Expand Down Expand Up @@ -604,8 +603,8 @@ def replace_token_with_symbol
token_to_symbol(t)
end

if rule.code
rule.code.references.each do |ref|
if rule.token_code
rule.token_code.references.each do |ref|
next if ref.type == :at

if !ref.referring_symbol.is_a?(Lrama::Lexer::Token::UserCode)
Expand Down Expand Up @@ -708,9 +707,9 @@ def validate_no_declared_type_reference!
errors = []

rules.each do |rule|
next unless rule.code
next unless rule.token_code

rule.code.references.select do |ref|
rule.token_code.references.select do |ref|
ref.type == :dollar && !ref.tag
end.each do |ref|
errors << "$#{ref.value} of '#{rule.lhs.id.s_value}' has no declared type"
Expand Down
6 changes: 4 additions & 2 deletions lib/lrama/grammar/rule.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Lrama
class Grammar
class Rule < Struct.new(:id, :lhs, :rhs, :code, :nullable, :precedence_sym, :lineno, keyword_init: true)
class Rule < Struct.new(:id, :lhs, :rhs, :token_code, :nullable, :precedence_sym, :lineno, keyword_init: true)
# TODO: Change this to display_name
def to_s
l = lhs.id.s_value
Expand Down Expand Up @@ -32,7 +32,9 @@ def initial_rule?
end

def translated_code
code&.translated_code
return nil unless token_code

Code::RuleAction.new(type: :rule_action, token_code: token_code).translated_code
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/lrama/output.rb
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ def user_actions
str = ""

@context.states.rules.each do |rule|
next unless rule.code
next unless rule.token_code

code = rule.code
code = rule.token_code
spaces = " " * (code.column - 1)

str << <<-STR
Expand Down
Loading

0 comments on commit 6726470

Please sign in to comment.