Skip to content

Commit

Permalink
CEF parser: disallow duplicated candidate in ranking; +2 test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
ikluft committed Sep 14, 2023
1 parent d5aae83 commit 7ef8db5
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 21 deletions.
51 changes: 33 additions & 18 deletions src/perl/prefvote/lib/PrefVote/Core/Input/CEF_Parser.pm
Original file line number Diff line number Diff line change
Expand Up @@ -802,42 +802,57 @@ sub
'ranking', 2,
sub
#line 64 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return [ (defined $_[2]) ? ($_[2]) : (), @{$_[1]} ]; }
{
# verify no duplicated choices/candidates in ranking
my %seen;
foreach my $ch_list ( @{$_[1]}) {
foreach my $eq_item ( @$ch_list ) {
if ( exists $seen{$eq_item} ) {
$_[0]->YYData->{ERRMSG} = "duplicate choice not allowed ($eq_item)";
$_[0]->YYError;
}
$seen{$eq_item} = 1;
}
}

# return ranking result
return [ (defined $_[2]) ? ($_[2]) : (), @{$_[1]} ];
}
],
[#Rule 7
'ranking', 2,
sub
#line 65 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 80 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return [ (defined $_[2]) ? ($_[2]) : () ]; }
],
[#Rule 8
'choice_list', 3,
sub
#line 69 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 84 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return [ @{$_[1]}, $_[3] ]; }
],
[#Rule 9
'choice_list', 1,
sub
#line 70 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 85 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return [ $_[1] ]; }
],
[#Rule 10
'equal_list', 3,
sub
#line 74 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 89 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return [ @{$_[1]}, $_[3] ]; }
],
[#Rule 11
'equal_list', 1,
sub
#line 75 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 90 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return [ $_[1] ]; }
],
[#Rule 12
'candidate', 1,
sub
#line 79 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 94 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return $_[1]; }
],
[#Rule 13
Expand All @@ -846,37 +861,37 @@ sub
[#Rule 14
'multipliers', 2,
sub
#line 84 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 99 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return { %{$_[1]}, %{$_[2]} }; }
],
[#Rule 15
'multipliers', 2,
sub
#line 85 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 100 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return { %{$_[1]}, %{$_[2]} }; }
],
[#Rule 16
'multipliers', 1,
sub
#line 86 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 101 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return $_[1]; }
],
[#Rule 17
'multipliers', 1,
sub
#line 87 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 102 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return $_[1]; }
],
[#Rule 18
'quantifier', 2,
sub
#line 91 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 106 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return { quantifier => $_[2]}; }
],
[#Rule 19
'weight', 2,
sub
#line 95 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 110 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{
if ( not ( $_[0]->YYData->{VOTE_DEF}{params}{weight_allowed} // 0 )) {
$_[0]->YYData->{ERRMSG} = "weight not permitted without weight_allowed flag";
Expand All @@ -888,33 +903,33 @@ sub
[#Rule 20
'words', 2,
sub
#line 105 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 120 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return $_[1] . " " . $_[2]; }
],
[#Rule 21
'words', 1,
sub
#line 106 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 121 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return "" . $_[1]; }
],
[#Rule 22
'word', 1,
sub
#line 110 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 125 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return "" . $_[1]; }
],
[#Rule 23
'word', 1,
sub
#line 111 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 126 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
{ return 0 + $_[1]; }
]
],
@_);
bless($self,$class);
}

#line 114 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"
#line 129 "/home/ikluft/src/github/prefvote/src/perl/prefvote/lib/PrefVote/Core/Input//CEF_Parser.yp"


sub _Error
Expand Down
17 changes: 16 additions & 1 deletion src/perl/prefvote/lib/PrefVote/Core/Input/CEF_Parser.yp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,22 @@ tag:
;

ranking:
choice_list multipliers { return [ (defined $_[2]) ? ($_[2]) : (), @{$_[1]} ]; }
choice_list multipliers {
# verify no duplicated choices/candidates in ranking
my %seen;
foreach my $ch_list ( @{$_[1]}) {
foreach my $eq_item ( @$ch_list ) {
if ( exists $seen{$eq_item} ) {
$_[0]->YYData->{ERRMSG} = "duplicate choice not allowed ($eq_item)";
$_[0]->YYError;
}
$seen{$eq_item} = 1;
}
}

# return ranking result
return [ (defined $_[2]) ? ($_[2]) : (), @{$_[1]} ];
}
| EMPTY_RANKING multipliers { return [ (defined $_[2]) ? ($_[2]) : () ]; }
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ cef-doc-example2.cvotes:
cef-doc-invalid3.cvotes:
error: "^Syntax error at position 12, expected EMPTY_RANKING INT WORD"
cef-doc-invalid4.cvotes:
error: "^Syntax error at position 12, expected EMPTY_RANKING INT WORD"
error: "^duplicate choice not allowed \\(Candidate A\\) at position 39, expected EMPTY_RANKING INT WORD"
cef-doc-invalid6.cvotes:
error: "^Syntax error at position 43, found EMPTY_RANKING '/EMPTY_RANKING/', expected INT WORD"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# My beautiful election
#/Candidates: Candidate A;Candidate B;Candidate C

Candidate A < Candidate B > Candidate C
Candidate A > Candidate B > Candidate A

0 comments on commit 7ef8db5

Please sign in to comment.