Skip to content

Commit dc84fcd

Browse files
authored
Merge pull request #821 from ruby/fix/empty-rule-alternatives
Reject %empty misuse in later rule alternatives
2 parents f606350 + eedae17 commit dc84fcd

3 files changed

Lines changed: 39 additions & 14 deletions

File tree

‎lib/lrama/parser.rb‎

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎parser.y‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,12 @@ rule
446446
IDENT_COLON named_ref? ":" rhs_list
447447
{
448448
result = val[3].map do |rhs|
449+
if rhs.reject {|sym| sym.is_a?(Grammar::Node::RuleRhs::Action) || sym.is_a?(Grammar::Node::RuleRhs::Prec) }.count > 1
450+
empties = rhs.select { |sym| sym.is_a?(Grammar::Node::RuleRhs::Empty) }
451+
empties.each do |empty|
452+
on_action_error("%empty on non-empty rule", empty)
453+
end
454+
end
449455
Grammar::Node::Rule.new(
450456
id: val[0],
451457
alias_name: val[1],
@@ -458,12 +464,6 @@ rule
458464
rhs_list:
459465
rhs
460466
{
461-
if val[0].reject {|sym| sym.is_a?(Grammar::Node::RuleRhs::Action) || sym.is_a?(Grammar::Node::RuleRhs::Prec) }.count > 1
462-
empties = val[0].select { |sym| sym.is_a?(Grammar::Node::RuleRhs::Empty) }
463-
empties.each do |empty|
464-
on_action_error("%empty on non-empty rule", empty)
465-
end
466-
end
467467
result = [val[0]]
468468
}
469469
| rhs_list "|" rhs

‎spec/lrama/parser_spec.rb‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4601,6 +4601,31 @@ class : keyword_class tSTRING keyword_end { code 1 }
46014601
ERROR
46024602
end
46034603
end
4604+
4605+
context "when %empty is misused in a later alternative" do
4606+
[
4607+
["A | B %empty", 13],
4608+
["A | %empty B", 11],
4609+
["A | %empty %empty", 11],
4610+
["A | A | B %empty", 17],
4611+
].each do |rhs, column|
4612+
it "rejects #{rhs}" do
4613+
y = <<~INPUT
4614+
%token A B
4615+
%%
4616+
start: #{rhs};
4617+
INPUT
4618+
4619+
parser = Lrama::Parser.new(y, "error_messages/parse.y")
4620+
4621+
expect { parser.parse }.to raise_error(ParseError, <<~ERROR)
4622+
error_messages/parse.y:3:#{column}: %empty on non-empty rule
4623+
3 | start: #{rhs};
4624+
| #{' ' * column}^~~~~~
4625+
ERROR
4626+
end
4627+
end
4628+
end
46044629
end
46054630
end
46064631

0 commit comments

Comments
 (0)