added lex error: DuplicateArguments

This commit is contained in:
Nick Liu 2022-12-29 01:12:30 +08:00
parent 78bcb6fb3e
commit 8eeca31fe6
3 changed files with 68 additions and 24 deletions

View file

@ -6,7 +6,7 @@
use crate::{ use crate::{
ast, ast,
error::{LexicalError, LexicalErrorType}, error::{LexicalError, LexicalErrorType},
function::{ArgumentList, parse_args, parse_params}, function::{ArgumentList, parse_args, parse_params, validate_arguments},
lexer, lexer,
context::set_context, context::set_context,
string::parse_strings, string::parse_strings,
@ -552,7 +552,8 @@ FuncDef: ast::Stmt = {
}; };
Parameters: ast::Arguments = { Parameters: ast::Arguments = {
"(" <a: (ParameterList<TypedParameter>)?> ")" => { "(" <a: (ParameterList<TypedParameter>)?> ")" =>? {
let args = validate_arguments(
a.unwrap_or_else(|| ast::Arguments { a.unwrap_or_else(|| ast::Arguments {
posonlyargs: vec![], posonlyargs: vec![],
args: vec![], args: vec![],
@ -562,6 +563,9 @@ Parameters: ast::Arguments = {
kwarg: None, kwarg: None,
defaults: vec![] defaults: vec![]
}) })
)?;
Ok(args)
} }
}; };
@ -774,8 +778,9 @@ NamedExpression: ast::Expr = {
}; };
LambdaDef: ast::Expr = { LambdaDef: ast::Expr = {
<location:@L> "lambda" <p:ParameterList<UntypedParameter>?> ":" <body:Test<"all">> <end_location:@R> => { <location:@L> "lambda" <p:ParameterList<UntypedParameter>?> ":" <body:Test<"all">> <end_location:@R> =>? {
let p = p.unwrap_or_else(|| { let p = validate_arguments(
p.unwrap_or_else(|| {
ast::Arguments { ast::Arguments {
posonlyargs: vec![], posonlyargs: vec![],
args: vec![], args: vec![],
@ -785,8 +790,10 @@ LambdaDef: ast::Expr = {
kwarg: None, kwarg: None,
defaults: vec![] defaults: vec![]
} }
}); }
ast::Expr { ))?;
Ok(ast::Expr {
location, location,
end_location: Some(end_location), end_location: Some(end_location),
custom: (), custom: (),
@ -794,7 +801,7 @@ LambdaDef: ast::Expr = {
args: Box::new(p), args: Box::new(p),
body: Box::new(body) body: Box::new(body)
} }
} })
} }
} }

View file

@ -21,6 +21,7 @@ pub enum LexicalErrorType {
TabError, TabError,
TabsAfterSpaces, TabsAfterSpaces,
DefaultArgumentError, DefaultArgumentError,
DuplicateArgumentError,
PositionalArgumentError, PositionalArgumentError,
UnpackedArgumentError, UnpackedArgumentError,
DuplicateKeywordArgumentError, DuplicateKeywordArgumentError,
@ -50,6 +51,9 @@ impl fmt::Display for LexicalErrorType {
LexicalErrorType::DefaultArgumentError => { LexicalErrorType::DefaultArgumentError => {
write!(f, "non-default argument follows default argument") write!(f, "non-default argument follows default argument")
} }
LexicalErrorType::DuplicateArgumentError => {
write!(f, "duplicate argument in function definition")
}
LexicalErrorType::DuplicateKeywordArgumentError => { LexicalErrorType::DuplicateKeywordArgumentError => {
write!(f, "keyword argument repeated") write!(f, "keyword argument repeated")
} }

View file

@ -10,6 +10,39 @@ pub struct ArgumentList {
type ParameterDefs = (Vec<ast::Arg>, Vec<ast::Arg>, Vec<ast::Expr>); type ParameterDefs = (Vec<ast::Arg>, Vec<ast::Arg>, Vec<ast::Expr>);
type ParameterDef = (ast::Arg, Option<ast::Expr>); type ParameterDef = (ast::Arg, Option<ast::Expr>);
pub fn validate_arguments(
arguments: ast::Arguments
) -> Result<ast::Arguments, LexicalError> {
let mut all_args: Vec<&ast::Located<ast::ArgData>> = vec![];
all_args.extend(arguments.posonlyargs.iter());
all_args.extend(arguments.args.iter());
if let Some(a) = &arguments.vararg {
all_args.push(a);
}
all_args.extend(arguments.kwonlyargs.iter());
if let Some(a) = &arguments.kwarg {
all_args.push(a);
}
let mut all_arg_names =
FxHashSet::with_hasher(Default::default());
for arg in all_args {
let arg_name = arg.node.arg.clone();
if !all_arg_names.insert(arg_name) {
return Err(LexicalError {
error: LexicalErrorType::DuplicateArgumentError,
location: arg.location,
});
}
}
return Ok(arguments);
}
pub fn parse_params( pub fn parse_params(
params: (Vec<ParameterDef>, Vec<ParameterDef>), params: (Vec<ParameterDef>, Vec<ParameterDef>),
) -> Result<ParameterDefs, LexicalError> { ) -> Result<ParameterDefs, LexicalError> {