Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3a5716d

Browse files
authored
Merge pull requestRustPython#4380 from nicku12345/lex_error_duplicate_function_args
add lex error for function args
2 parents2eb87ca +7e3c59d commit3a5716d

File tree

5 files changed

+74
-34
lines changed

5 files changed

+74
-34
lines changed

‎Lib/test/test_compile.py‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ def test_debug_assignment(self):
4242
self.assertEqual(__debug__,prev)
4343
setattr(builtins,'__debug__',prev)
4444

45-
# TODO: RUSTPYTHON
46-
@unittest.expectedFailure
4745
deftest_argument_handling(self):
4846
# detect duplicate positional and keyword arguments
4947
self.assertRaises(SyntaxError,eval,'lambda a,a:0')

‎Lib/test/test_positional_only_arg.py‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ def assertRaisesSyntaxError(self, codestr, regex="invalid syntax"):
2222
withself.assertRaisesRegex(SyntaxError,regex):
2323
compile(codestr+"\n","<test>","single")
2424

25-
# TODO: RUSTPYTHON
26-
@unittest.expectedFailure
2725
deftest_invalid_syntax_errors(self):
2826
check_syntax_error(self,"def f(a, b = 5, /, c): pass","non-default argument follows default argument")
2927
check_syntax_error(self,"def f(a = 5, b, /, c): pass","non-default argument follows default argument")
@@ -45,8 +43,6 @@ def test_invalid_syntax_errors(self):
4543
check_syntax_error(self,"def f(a, /, c, /, d, *, e): pass")
4644
check_syntax_error(self,"def f(a, *, c, /, d, e): pass")
4745

48-
# TODO: RUSTPYTHON
49-
@unittest.expectedFailure
5046
deftest_invalid_syntax_errors_async(self):
5147
check_syntax_error(self,"async def f(a, b = 5, /, c): pass","non-default argument follows default argument")
5248
check_syntax_error(self,"async def f(a = 5, b, /, c): pass","non-default argument follows default argument")
@@ -240,8 +236,6 @@ def test_lambdas(self):
240236
x=lambdaa,b,/, :a+b
241237
self.assertEqual(x(1,2),3)
242238

243-
# TODO: RUSTPYTHON
244-
@unittest.expectedFailure
245239
deftest_invalid_syntax_lambda(self):
246240
check_syntax_error(self,"lambda a, b = 5, /, c: None","non-default argument follows default argument")
247241
check_syntax_error(self,"lambda a = 5, b, /, c: None","non-default argument follows default argument")

‎compiler/parser/python.lalrpop‎

Lines changed: 40 additions & 26 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

@@ -663,7 +667,7 @@ TypedParameter: ast::Arg = {
663667
// TODO: figure out another grammar that makes this inline no longer required.
664668
#[inline]
665669
ParameterListStarArgs<ArgType>: (Option<Box<ast::Arg>>, Vec<ast::Arg>, Vec<ast::Expr>, Option<Box<ast::Arg>>) = {
666-
"*" <va:ArgType?> <kw:("," ParameterDef<ArgType>)*> <kwarg:("," KwargParameter<ArgType>)?> => {
670+
<location:@L>"*" <va:ArgType?> <kw:("," ParameterDef<ArgType>)*> <kwarg:("," KwargParameter<ArgType>)?> =>? {
667671
// Extract keyword arguments:
668672
let mut kwonlyargs = Vec::new();
669673
let mut kw_defaults = Vec::new();
@@ -678,10 +682,17 @@ ParameterListStarArgs<ArgType>: (Option<Box<ast::Arg>>, Vec<ast::Arg>, Vec<ast::
678682
}
679683
kwargs.extend(kwonlyargs.into_iter());
680684

685+
if va.is_none() && kwargs.is_empty() && kwarg.is_none() {
686+
Err(LexicalError {
687+
error: LexicalErrorType::OtherError("named arguments must follow bare *".to_string()),
688+
location: location,
689+
})?
690+
}
691+
681692
let kwarg = kwarg.map(|n| n.1).flatten();
682693
let va = va.map(Box::new);
683694

684-
(va, kwargs, kw_defaults, kwarg)
695+
Ok((va, kwargs, kw_defaults, kwarg))
685696
}
686697
};
687698

@@ -774,27 +785,30 @@ NamedExpression: ast::Expr = {
774785
};
775786

776787
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![]
788+
<location:@L> "lambda" <p:ParameterList<UntypedParameter>?> ":" <body:Test<"all">> <end_location:@R> =>? {
789+
let p = validate_arguments(
790+
p.unwrap_or_else(|| {
791+
ast::Arguments {
792+
posonlyargs: vec![],
793+
args: vec![],
794+
vararg: None,
795+
kwonlyargs: vec![],
796+
kw_defaults: vec![],
797+
kwarg: None,
798+
defaults: vec![]
799+
}
787800
}
788-
});
789-
ast::Expr {
801+
))?;
802+
803+
Ok(ast::Expr {
790804
location,
791805
end_location: Some(end_location),
792806
custom: (),
793807
node: ast::ExprKind::Lambda {
794808
args: Box::new(p),
795809
body: Box::new(body)
796810
}
797-
}
811+
})
798812
}
799813
}
800814

‎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(String),
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(arg_name) =>{
55+
write!(f,"duplicate argument '{arg_name}' in function definition")
56+
}
5357
LexicalErrorType::DuplicateKeywordArgumentError =>{
5458
write!(f,"keyword argument repeated")
5559
}

‎compiler/parser/src/function.rs‎

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

13+
pubfnvalidate_arguments(arguments: ast::Arguments) ->Result<ast::Arguments,LexicalError>{
14+
letmut all_args:Vec<&ast::Located<ast::ArgData>> =vec![];
15+
16+
all_args.extend(arguments.posonlyargs.iter());
17+
all_args.extend(arguments.args.iter());
18+
19+
ifletSome(a) =&arguments.vararg{
20+
all_args.push(a);
21+
}
22+
23+
all_args.extend(arguments.kwonlyargs.iter());
24+
25+
ifletSome(a) =&arguments.kwarg{
26+
all_args.push(a);
27+
}
28+
29+
letmut all_arg_names =FxHashSet::with_hasher(Default::default());
30+
for argin all_args{
31+
let arg_name =&arg.node.arg;
32+
if !all_arg_names.insert(arg_name){
33+
returnErr(LexicalError{
34+
error:LexicalErrorType::DuplicateArgumentError(arg_name.to_string()),
35+
location: arg.location,
36+
});
37+
}
38+
}
39+
40+
Ok(arguments)
41+
}
42+
1343
pubfnparse_params(
1444
params:(Vec<ParameterDef>,Vec<ParameterDef>),
1545
) ->Result<ParameterDefs,LexicalError>{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp