Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support %destructor declaration #385

Merged
merged 1 commit into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Steepfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ target :lib do
signature "sig"

check "lib/lrama/grammar/binding.rb"
check "lib/lrama/grammar/code/destructor_code.rb"
check "lib/lrama/grammar/code/printer_code.rb"
check "lib/lrama/grammar/code.rb"
check "lib/lrama/grammar/counter.rb"
Expand All @@ -14,6 +15,7 @@ target :lib do
check "lib/lrama/grammar/symbols"
check "lib/lrama/grammar/percent_code.rb"
check "lib/lrama/grammar/precedence.rb"
check "lib/lrama/grammar/destructor.rb"
check "lib/lrama/grammar/printer.rb"
check "lib/lrama/grammar/reference.rb"
check "lib/lrama/grammar/rule_builder.rb"
Expand Down
9 changes: 8 additions & 1 deletion lib/lrama/grammar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require "lrama/grammar/binding"
require "lrama/grammar/code"
require "lrama/grammar/counter"
require "lrama/grammar/destructor"
require "lrama/grammar/error_token"
require "lrama/grammar/parameterizing_rule"
require "lrama/grammar/percent_code"
Expand Down Expand Up @@ -34,7 +35,7 @@ class Grammar
def_delegators "@symbols_resolver", :symbols, :nterms, :terms, :add_nterm, :add_term,
:find_symbol_by_number!, :find_symbol_by_id!, :token_to_symbol,
:find_symbol_by_s_value!, :fill_symbol_number, :fill_nterm_type,
:fill_printer, :fill_error_token, :sort_by_number!
:fill_printer, :fill_destructor, :fill_error_token, :sort_by_number!


def initialize(rule_counter)
Expand All @@ -43,6 +44,7 @@ def initialize(rule_counter)
# Code defined by "%code"
@percent_codes = []
@printers = []
@destructors = []
@error_tokens = []
@symbols_resolver = Grammar::Symbols::Resolver.new
@types = []
Expand All @@ -65,6 +67,10 @@ def add_percent_code(id:, code:)
@percent_codes << PercentCode.new(id.s_value, code.s_value)
end

def add_destructor(ident_or_tags:, token_code:, lineno:)
@destructors << Destructor.new(ident_or_tags: ident_or_tags, token_code: token_code, lineno: lineno)
end

def add_printer(ident_or_tags:, token_code:, lineno:)
@printers << Printer.new(ident_or_tags: ident_or_tags, token_code: token_code, lineno: lineno)
end
Expand Down Expand Up @@ -345,6 +351,7 @@ def fill_symbols
fill_symbol_number
fill_nterm_type(@types)
fill_printer(@printers)
fill_destructor(@destructors)
fill_error_token(@error_tokens)
sort_by_number!
end
Expand Down
1 change: 1 addition & 0 deletions lib/lrama/grammar/code.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "forwardable"
require "lrama/grammar/code/destructor_code"
require "lrama/grammar/code/initial_action_code"
require "lrama/grammar/code/no_reference_code"
require "lrama/grammar/code/printer_code"
Expand Down
40 changes: 40 additions & 0 deletions lib/lrama/grammar/code/destructor_code.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module Lrama
class Grammar
class Code
class DestructorCode < Code
def initialize(type:, token_code:, tag:)
super(type: type, token_code: token_code)
@tag = tag
end

private

# * ($$) *yyvaluep
# * (@$) *yylocationp
# * ($:$) error
# * ($1) error
# * (@1) error
# * ($:1) error
def reference_to_c(ref)
case
when ref.type == :dollar && ref.name == "$" # $$
member = @tag.member
"((*yyvaluep).#{member})"
when ref.type == :at && ref.name == "$" # @$
"(*yylocationp)"
when ref.type == :index && ref.name == "$" # $:$
raise "$:#{ref.value} can not be used in #{type}."
when ref.type == :dollar # $n
raise "$#{ref.value} can not be used in #{type}."
when ref.type == :at # @n
raise "@#{ref.value} can not be used in #{type}."
when ref.type == :index # $:n
raise "$:#{ref.value} can not be used in #{type}."
else
raise "Unexpected. #{self}, #{ref}"
end
end
end
end
end
end
9 changes: 9 additions & 0 deletions lib/lrama/grammar/destructor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Lrama
class Grammar
class Destructor < Struct.new(:ident_or_tags, :token_code, :lineno, keyword_init: true)
def translated_code(tag)
Code::DestructorCode.new(type: :destructor, token_code: token_code, tag: tag).translated_code
end
end
end
end
6 changes: 4 additions & 2 deletions lib/lrama/grammar/symbol.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
module Lrama
class Grammar
class Symbol
attr_accessor :id, :alias_name, :tag, :number, :token_id, :nullable, :precedence, :printer, :error_token, :first_set, :first_set_bitmap
attr_accessor :id, :alias_name, :tag, :number, :token_id, :nullable, :precedence,
:printer, :destructor, :error_token, :first_set, :first_set_bitmap
attr_reader :term
attr_writer :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol

def initialize(id:, term:, alias_name: nil, number: nil, tag: nil, token_id: nil, nullable: nil, precedence: nil, printer: nil)
def initialize(id:, term:, alias_name: nil, number: nil, tag: nil, token_id: nil, nullable: nil, precedence: nil, printer: nil, destructor: nil)
@id = id
@alias_name = alias_name
@number = number
Expand All @@ -21,6 +22,7 @@ def initialize(id:, term:, alias_name: nil, number: nil, tag: nil, token_id: nil
@nullable = nullable
@precedence = precedence
@printer = printer
@destructor = destructor
end

def term?
Expand Down
17 changes: 17 additions & 0 deletions lib/lrama/grammar/symbols/resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,23 @@ def fill_printer(printers)
end
end

def fill_destructor(destructors)
symbols.each do |sym|
destructors.each do |destructor|
destructor.ident_or_tags.each do |ident_or_tag|
case ident_or_tag
when Lrama::Lexer::Token::Ident
sym.destructor = destructor if sym.id == ident_or_tag
when Lrama::Lexer::Token::Tag
sym.destructor = destructor if sym.tag == ident_or_tag
else
raise "Unknown token type. #{destructor}"
end
end
end
end
end

def fill_error_token(error_tokens)
symbols.each do |sym|
error_tokens.each do |token|
Expand Down
1 change: 1 addition & 0 deletions lib/lrama/lexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Lexer
%define
%require
%printer
%destructor
%lex-param
%parse-param
%initial-action
Expand Down
19 changes: 19 additions & 0 deletions lib/lrama/output.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,25 @@ def symbol_actions_for_printer
str
end

def symbol_actions_for_destructor
str = ""

@grammar.symbols.each do |sym|
next unless sym.destructor

str << <<-STR
case #{sym.enum_name}: /* #{sym.comment} */
#line #{sym.destructor.lineno} "#{@grammar_file_path}"
{#{sym.destructor.translated_code(sym.tag)}}
#line [@oline@] [@ofile@]
break;

STR
end

str
end

# b4_user_initial_action
def user_initial_action(comment = "")
return "" unless @grammar.initial_action
Expand Down
Loading