Skip to content

Commit

Permalink
Merge pull request #477 from ydah/fix-an-error
Browse files Browse the repository at this point in the history
Fix an error when `str.length` is greater than `length`
  • Loading branch information
ydah authored Dec 19, 2024
2 parents 5e819cf + 44be665 commit d6946ec
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/lrama/counterexamples/derivation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def _render_for_report(derivation, offset, strings, index)
str << "#{item.next_sym.display_name}"
length = _render_for_report(derivation.left, len, strings, index + 1)
# I want String#ljust!
str << " " * (length - str.length)
str << " " * (length - str.length) if length > str.length
else
str << " • #{item.symbols_after_dot.map(&:display_name).join(" ")} "
return str.length
Expand Down
86 changes: 86 additions & 0 deletions spec/lrama/counterexamples_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,92 @@
4: digit '+' digit •
STR
end

context "when the grammar has a long rule name" do
let(:y) do
<<~STR
%{
// Prologue
%}
%union {
int i;
}
%token <i> digit
%type <i> stmt
%type <i> expr1
%type <i> long_long_long_name_expr2
%%
stmt : expr1
| long_long_long_name_expr2
;
expr1 : digit '+' digit
;
long_long_long_name_expr2 : digit '+' digit
;
%%
STR
end

it "build counterexamples of R/R conflicts" do
grammar = Lrama::Parser.new(y, "parse.y").parse
grammar.prepare
grammar.validate!
states = Lrama::States.new(grammar)
states.compute
counterexamples = Lrama::Counterexamples.new(states)

# State 7
#
# 3 expr1: digit '+' digit • ["end of file"]
# 4 long_long_long_name_expr2: digit '+' digit • ["end of file"]
#
# "end of file" reduce using rule 3 (expr1)
# "end of file" reduce using rule 4 (long_long_long_name_expr2)
state_7 = states.states[7]
examples = counterexamples.compute(state_7)
expect(examples.count).to eq 1
example = examples[0]

expect(example.type).to eq :reduce_reduce
# Reduce Conflict
expect(example.path1.map(&:to).map(&:item).map(&:to_s)).to eq([
"$accept: • stmt \"end of file\" (rule 0)",
"stmt: • expr1 (rule 1)",
"expr1: • digit '+' digit (rule 3)",
"expr1: digit • '+' digit (rule 3)",
"expr1: digit '+' • digit (rule 3)",
"expr1: digit '+' digit • (rule 3)"
])
expect(example.derivations1.render_for_report).to eq(<<~STR.chomp)
0: stmt "end of file"
1: expr1
3: digit '+' digit •
STR
# Reduce Conflict
expect(example.path2.map(&:to).map(&:item).map(&:to_s)).to eq([
"$accept: • stmt \"end of file\" (rule 0)",
"stmt: • long_long_long_name_expr2 (rule 2)",
"long_long_long_name_expr2: • digit '+' digit (rule 4)",
"long_long_long_name_expr2: digit • '+' digit (rule 4)",
"long_long_long_name_expr2: digit '+' • digit (rule 4)",
"long_long_long_name_expr2: digit '+' digit • (rule 4)"
])
expect(example.derivations2.render_for_report).to eq(<<~STR.chomp)
0: stmt "end of file"
2: long_long_long_name_expr2
4: digit '+' digit •
STR
end
end
end

describe "target state item will be start item when finding shift conflict shortest state items" do
Expand Down

0 comments on commit d6946ec

Please sign in to comment.