Skip to content

Commit

Permalink
Support %destructor declaration
Browse files Browse the repository at this point in the history
  • Loading branch information
yui-knk committed Mar 20, 2024
1 parent e09e1ea commit ad884e4
Show file tree
Hide file tree
Showing 20 changed files with 424 additions and 88 deletions.
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

0 comments on commit ad884e4

Please sign in to comment.