Skip to content

Commit 62fd967

Browse files
committed
added lex error: DuplicateArguments
1 parent 2eb87ca commit 62fd967

File tree

3 files changed

+68
-24
lines changed

3 files changed

+68
-24
lines changed

compiler/parser/python.lalrpop

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use crate::{
77
ast,
88
error::{LexicalError, LexicalErrorType},
9-
function::{ArgumentList, parse_args, parse_params},
9+
function::{ArgumentList, parse_args, parse_params, validate_arguments},
1010
lexer,
1111
context::set_context,
1212
string::parse_strings,
@@ -552,16 +552,20 @@ FuncDef: ast::Stmt = {
552552
};
553553

554554
Parameters: ast::Arguments = {
555-
"(" <a: (ParameterList<TypedParameter>)?> ")" => {
556-
a.unwrap_or_else(|| ast::Arguments {
557-
posonlyargs: vec![],
558-
args: vec![],
559-
vararg: None,
560-
kwonlyargs: vec![],
561-
kw_defaults: vec![],
562-
kwarg: None,
563-
defaults: vec![]
564-
})
555+
"(" <a: (ParameterList<TypedParameter>)?> ")" =>? {
556+
let args = validate_arguments(
557+
a.unwrap_or_else(|| ast::Arguments {
558+
posonlyargs: vec![],
559+
args: vec![],
560+
vararg: None,
561+
kwonlyargs: vec![],
562+
kw_defaults: vec![],
563+
kwarg: None,
564+
defaults: vec![]
565+
})
566+
)?;
567+
568+
Ok(args)
565569
}
566570
};
567571

@@ -774,27 +778,30 @@ NamedExpression: ast::Expr = {
774778
};
775779

776780
LambdaDef: ast::Expr = {
777-
<location:@L> "lambda" <p:ParameterList<UntypedParameter>?> ":" <body:Test<"all">> <end_location:@R> => {
778-
let p = p.unwrap_or_else(|| {
779-
ast::Arguments {
780-
posonlyargs: vec![],
781-
args: vec![],
782-
vararg: None,
783-
kwonlyargs: vec![],
784-
kw_defaults: vec![],
785-
kwarg: None,
786-
defaults: vec![]
781+
<location:@L> "lambda" <p:ParameterList<UntypedParameter>?> ":" <body:Test<"all">> <end_location:@R> =>? {
782+
let p = validate_arguments(
783+
p.unwrap_or_else(|| {
784+
ast::Arguments {
785+
posonlyargs: vec![],
786+
args: vec![],
787+
vararg: None,
788+
kwonlyargs: vec![],
789+
kw_defaults: vec![],
790+
kwarg: None,
791+
defaults: vec![]
792+
}
787793
}
788-
});
789-
ast::Expr {
794+
))?;
795+
796+
Ok(ast::Expr {
790797
location,
791798
end_location: Some(end_location),
792799
custom: (),
793800
node: ast::ExprKind::Lambda {
794801
args: Box::new(p),
795802
body: Box::new(body)
796803
}
797-
}
804+
})
798805
}
799806
}
800807

compiler/parser/src/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub enum LexicalErrorType {
2121
TabError,
2222
TabsAfterSpaces,
2323
DefaultArgumentError,
24+
DuplicateArgumentError,
2425
PositionalArgumentError,
2526
UnpackedArgumentError,
2627
DuplicateKeywordArgumentError,
@@ -50,6 +51,9 @@ impl fmt::Display for LexicalErrorType {
5051
LexicalErrorType::DefaultArgumentError => {
5152
write!(f, "non-default argument follows default argument")
5253
}
54+
LexicalErrorType::DuplicateArgumentError => {
55+
write!(f, "duplicate argument in function definition")
56+
}
5357
LexicalErrorType::DuplicateKeywordArgumentError => {
5458
write!(f, "keyword argument repeated")
5559
}

compiler/parser/src/function.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,39 @@ pub struct ArgumentList {
1010
type ParameterDefs = (Vec<ast::Arg>, Vec<ast::Arg>, Vec<ast::Expr>);
1111
type ParameterDef = (ast::Arg, Option<ast::Expr>);
1212

13+
pub fn validate_arguments(
14+
arguments: ast::Arguments
15+
) -> Result<ast::Arguments, LexicalError> {
16+
let mut all_args: Vec<&ast::Located<ast::ArgData>> = vec![];
17+
18+
all_args.extend(arguments.posonlyargs.iter());
19+
all_args.extend(arguments.args.iter());
20+
21+
if let Some(a) = &arguments.vararg {
22+
all_args.push(a);
23+
}
24+
25+
all_args.extend(arguments.kwonlyargs.iter());
26+
27+
if let Some(a) = &arguments.kwarg {
28+
all_args.push(a);
29+
}
30+
31+
let mut all_arg_names =
32+
FxHashSet::with_hasher(Default::default());
33+
for arg in all_args {
34+
let arg_name = arg.node.arg.clone();
35+
if !all_arg_names.insert(arg_name) {
36+
return Err(LexicalError {
37+
error: LexicalErrorType::DuplicateArgumentError,
38+
location: arg.location,
39+
});
40+
}
41+
}
42+
43+
return Ok(arguments);
44+
}
45+
1346
pub fn parse_params(
1447
params: (Vec<ParameterDef>, Vec<ParameterDef>),
1548
) -> Result<ParameterDefs, LexicalError> {

0 commit comments

Comments
 (0)