Skip to content

Commit

Permalink
Merge pull request #269 from yui-knk/symbol_to_plain_object
Browse files Browse the repository at this point in the history
Performance improvement
  • Loading branch information
yui-knk authored Nov 26, 2023
2 parents b027362 + 67693c3 commit a49ab82
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 20 deletions.
17 changes: 15 additions & 2 deletions lib/lrama/grammar/symbol.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,23 @@

module Lrama
class Grammar
class Symbol < Struct.new(:id, :alias_name, :number, :tag, :term, :token_id, :nullable, :precedence, :printer, :error_token, keyword_init: true)
attr_accessor :first_set, :first_set_bitmap
class Symbol
attr_accessor :id, :alias_name, :tag, :number, :token_id, :nullable, :precedence, :printer, :error_token, :first_set, :first_set_bitmap
attr_reader :term
attr_writer :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol

def initialize(id:, alias_name: nil, number: nil, tag: nil, term:, token_id: nil, nullable: nil, precedence: nil, printer: nil)
@id = id
@alias_name = alias_name
@number = number
@tag = tag
@term = term
@token_id = token_id
@nullable = nullable
@precedence = precedence
@printer = printer
end

def term?
term
end
Expand Down
2 changes: 1 addition & 1 deletion spec/lrama/grammar/rule_builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
describe "@user_code" do
let(:location) { Lrama::Lexer::Location.new(first_line: 1, first_column: 0, last_line: 1, last_column: 4) }
let(:token_1) { Lrama::Lexer::Token::UserCode.new(s_value: "code 1", location: location) }
let(:sym) { Lrama::Grammar::Symbol.new(id: Lrama::Lexer::Token::Ident.new(s_value: "tPLUS")) }
let(:sym) { Lrama::Grammar::Symbol.new(id: Lrama::Lexer::Token::Ident.new(s_value: "tPLUS"), term: true) }

context "@user_code is not nil" do
it "sets @user_code to be nil and add previous user_code to rhs" do
Expand Down
8 changes: 4 additions & 4 deletions spec/lrama/grammar/symbol_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
describe "#enum_name" do
describe "symbol is accept_symbol" do
it "returns 'YYSYMBOL_YYACCEPT'" do
sym = described_class.new(id: token_class::Ident.new(s_value: "$accept"))
sym = described_class.new(id: token_class::Ident.new(s_value: "$accept"), term: false)
sym.accept_symbol = true

expect(sym.enum_name).to eq("YYSYMBOL_YYACCEPT")
Expand All @@ -13,7 +13,7 @@

describe "symbol is eof_symbol" do
it "returns 'YYSYMBOL_YYEOF'" do
sym = described_class.new(id: token_class::Ident.new(s_value: "YYEOF"), alias_name: "\"end of file\"", token_id: 0)
sym = described_class.new(id: token_class::Ident.new(s_value: "YYEOF"), alias_name: "\"end of file\"", token_id: 0, term: true)
sym.number = 0
sym.eof_symbol = true

Expand Down Expand Up @@ -57,7 +57,7 @@
describe "#comment" do
describe "symbol is accept_symbol" do
it "returns s_value" do
sym = described_class.new(id: token_class::Ident.new(s_value: "$accept"))
sym = described_class.new(id: token_class::Ident.new(s_value: "$accept"), term: false)
sym.accept_symbol = true

expect(sym.comment).to eq("$accept")
Expand All @@ -66,7 +66,7 @@

describe "symbol is eof_symbol" do
it "returns alias_name" do
sym = described_class.new(id: token_class::Ident.new(s_value: "YYEOF"), alias_name: "\"end of file\"", token_id: 0)
sym = described_class.new(id: token_class::Ident.new(s_value: "YYEOF"), alias_name: "\"end of file\"", token_id: 0, term: true)
sym.number = 0
sym.eof_symbol = true

Expand Down
26 changes: 13 additions & 13 deletions spec/lrama/parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
expect(grammar.lex_param).to eq("struct lex_params *p")
expect(grammar.parse_param).to eq("struct parse_params *p")
expect(grammar.initial_action).to eq(Code::InitialActionCode.new(type: :initial_action, token_code: T::UserCode.new(s_value: "\n initial_action_func(@$);\n")))
expect(grammar.symbols.sort_by(&:number)).to eq([
expect(grammar.symbols.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "EOI"), alias_name: "\"EOI\"", number: 0, tag: nil, term: true, token_id: 0, nullable: false, precedence: nil, printer: nil),
Sym.new(id: T::Ident.new(s_value: "YYerror"), alias_name: "error", number: 1, tag: nil, term: true, token_id: 256, nullable: false, precedence: nil, printer: nil),
Sym.new(id: T::Ident.new(s_value: "YYUNDEF"), alias_name: "\"invalid token\"", number: 2, tag: nil, term: true, token_id: 257, nullable: false, precedence: nil, printer: nil),
Expand Down Expand Up @@ -417,7 +417,7 @@
y = File.read(fixture_path(path))
grammar = Lrama::Parser.new(y, path).parse

expect(grammar.nterms.sort_by(&:number)).to eq([
expect(grammar.nterms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 1, nullable: true),
Sym.new(id: T::Ident.new(s_value: "stmt"), alias_name: nil, number: 8, tag: nil, term: false, token_id: 2, nullable: true),
Expand Down Expand Up @@ -563,7 +563,7 @@
y = File.read(fixture_path(path))
grammar = Lrama::Parser.new(y, path).parse

expect(grammar.nterms.sort_by(&:number)).to eq([
expect(grammar.nterms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 5, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 1, nullable: true),
Sym.new(id: T::Ident.new(s_value: "option_number"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 2, nullable: true),
Expand Down Expand Up @@ -652,7 +652,7 @@
y.sub!('option(', 'option (')
grammar = Lrama::Parser.new(y, path).parse

expect(grammar.nterms.sort_by(&:number)).to eq([
expect(grammar.nterms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 5, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 1, nullable: true),
Sym.new(id: T::Ident.new(s_value: "option_number"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 2, nullable: true),
Expand Down Expand Up @@ -740,7 +740,7 @@
y = File.read(fixture_path(path))
grammar = Lrama::Parser.new(y, path).parse

expect(grammar.nterms.sort_by(&:number)).to eq([
expect(grammar.nterms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 1, nullable: false),
Sym.new(id: T::Ident.new(s_value: "option_bar"), alias_name: nil, number: 8, tag: nil, term: false, token_id: 2, nullable: true),
Expand Down Expand Up @@ -800,7 +800,7 @@
y = File.read(fixture_path(path))
grammar = Lrama::Parser.new(y, path).parse

expect(grammar.nterms.sort_by(&:number)).to eq([
expect(grammar.nterms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 5, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 1, nullable: false),
Sym.new(id: T::Ident.new(s_value: "nonempty_list_number"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 2, nullable: false),
Expand Down Expand Up @@ -894,7 +894,7 @@
y = File.read(fixture_path(path))
grammar = Lrama::Parser.new(y, path).parse

expect(grammar.nterms.sort_by(&:number)).to eq([
expect(grammar.nterms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 5, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 1, nullable: true),
Sym.new(id: T::Ident.new(s_value: "list_number"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 2, nullable: true),
Expand Down Expand Up @@ -984,7 +984,7 @@
y = File.read(fixture_path(path))
grammar = Lrama::Parser.new(y, path).parse

expect(grammar.nterms.sort_by(&:number)).to eq([
expect(grammar.nterms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 5, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 1, nullable: false),
Sym.new(id: T::Ident.new(s_value: "separated_nonempty_list_number"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 2, nullable: false),
Expand Down Expand Up @@ -1046,7 +1046,7 @@
y = File.read(fixture_path(path))
grammar = Lrama::Parser.new(y, path).parse

expect(grammar.nterms.sort_by(&:number)).to eq([
expect(grammar.nterms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 5, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 1, nullable: true),
Sym.new(id: T::Ident.new(s_value: "separated_list_number"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 2, nullable: true),
Expand Down Expand Up @@ -1201,7 +1201,7 @@ class : keyword_class tSTRING keyword_end { code 1 }
INPUT
grammar = Lrama::Parser.new(y, "parse.y").parse

expect(grammar.terms.sort_by(&:number)).to eq([
expect(grammar.terms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "EOI"), alias_name: "\"EOI\"", number: 0, tag: nil, term: true, token_id: 0, nullable: false, precedence: nil),
Sym.new(id: T::Ident.new(s_value: "YYerror"), alias_name: "error", number: 1, tag: nil, term: true, token_id: 256, nullable: false, precedence: nil),
Sym.new(id: T::Ident.new(s_value: "YYUNDEF"), alias_name: "\"invalid token\"", number: 2, tag: nil, term: true, token_id: 257, nullable: false, precedence: nil),
Expand Down Expand Up @@ -1258,7 +1258,7 @@ class : keyword_class { code 1 } tSTRING { code 2 } keyword_end { code 3 }
INPUT
grammar = Lrama::Parser.new(y, "parse.y").parse

expect(grammar.nterms.sort_by(&:number)).to eq([
expect(grammar.nterms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 11, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 12, tag: nil, term: false, token_id: 1, nullable: false),
Sym.new(id: T::Ident.new(s_value: "class"), alias_name: nil, number: 13, tag: T::Tag.new(s_value: "<i>"), term: false, token_id: 2, nullable: false),
Expand Down Expand Up @@ -1494,7 +1494,7 @@ class : keyword_class tSTRING keyword_end { code 1 }
INPUT
grammar = Lrama::Parser.new(y, "parse.y").parse

expect(grammar.terms.sort_by(&:number)).to eq([
expect(grammar.terms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "EOI"), alias_name: "\"EOI\"", number: 0, tag: nil, term: true, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "YYerror"), alias_name: "error", number: 1, tag: nil, term: true, token_id: 256, nullable: false),
Sym.new(id: T::Ident.new(s_value: "YYUNDEF"), alias_name: "\"invalid token\"", number: 2, tag: nil, term: true, token_id: 257, nullable: false),
Expand Down Expand Up @@ -1543,7 +1543,7 @@ class : keyword_class tSTRING keyword_end { code 1 }
INPUT
grammar = Lrama::Parser.new(y, "parse.y").parse

expect(grammar.terms.sort_by(&:number)).to eq([
expect(grammar.terms.sort_by(&:number)).to match_symbols([
Sym.new(id: T::Ident.new(s_value: "EOI"), alias_name: "\"EOI\"", number: 0, tag: nil, term: true, token_id: 0, nullable: false, precedence: nil),
Sym.new(id: T::Ident.new(s_value: "YYerror"), alias_name: "error", number: 1, tag: nil, term: true, token_id: 256, nullable: false, precedence: nil),
Sym.new(id: T::Ident.new(s_value: "YYUNDEF"), alias_name: "\"invalid token\"", number: 2, tag: nil, term: true, token_id: 257, nullable: false, precedence: nil),
Expand Down
108 changes: 108 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,113 @@ def windows?
end
end

module LramaCustomMatchers
class SymbolMatcher
attr_reader :expected, :target

def initialize(expected)
@expected = expected
@_failure_message = nil
end

def matches?(target)
@target = target

if !@expected.is_a?(Lrama::Grammar::Symbol)
@_failure_message = "expected #{@expected.inspect} to be Lrama::Grammar::Symbol"
return false
end

if !@target.is_a?(Lrama::Grammar::Symbol)
@_failure_message = "expected #{@target.inspect} to be Lrama::Grammar::Symbol"
return false
end

@expected.id == @target.id &&
@expected.alias_name == @target.alias_name &&
@expected.number == @target.number &&
@expected.tag == @target.tag &&
@expected.term == @target.term &&
@expected.token_id == @target.token_id &&
@expected.nullable == @target.nullable &&
@expected.precedence == @target.precedence &&
@expected.printer == @target.printer &&
@expected.error_token == @target.error_token
end

def failure_message
return @_failure_message if @_failure_message

"expected #{@target.inspect} to match with #{@expected.inspect}"
end

def failure_message_when_negated
return @_failure_message if @_failure_message

"expected #{@target.inspect} not to match with #{@expected.inspect}"
end
end

class SymbolsMatcher
attr_reader :expected, :target

def initialize(expected)
@expected = expected
@_failure_message = nil
end

def matches?(target)
@target = target

if !@expected.is_a?(Array)
@_failure_message = "expected #{@expected.inspect} to be Array"
return false
end

if !@target.is_a?(Array)
@_failure_message = "expected #{@target.inspect} to be Array"
return false
end

if @expected.count != @target.count
@_failure_message = "expected the number of array to be same (#{@expected.count} != #{@target.count})"
return false
end

@not_matched = []

@expected.zip(@target).each do |expected, actual|
matcher = SymbolMatcher.new(expected)
unless matcher.matches?(actual)
@not_matched << matcher
end
end

@not_matched.empty?
end

def failure_message
return @_failure_message if @_failure_message

@not_matched.map(&:failure_message).join("\n")
end

def failure_message_when_negated
return @_failure_message if @_failure_message

@not_matched.map(&:failure_message_when_negated).join("\n")
end
end

def match_symbol(expected)
SymbolMatcher.new(expected)
end

def match_symbols(expected)
SymbolsMatcher.new(expected)
end
end

RSpec.configure do |config|
# Disable RSpec exposing methods globally on `Module` and `main`
config.disable_monkey_patching!
Expand All @@ -45,6 +152,7 @@ def windows?
end

config.include(RspecHelper)
config.include(LramaCustomMatchers)

# Allow to limit the run of the specs
# NOTE: Please do not commit the filter option.
Expand Down

0 comments on commit a49ab82

Please sign in to comment.