New Arguments and Arg/ArgWithDefault AST representation (#59)
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
use crate::{
|
||||
ast::{self as ast, Ranged},
|
||||
lexer::{LexicalError, LexicalErrorType},
|
||||
function::{ArgumentList, parse_args, parse_params, validate_arguments},
|
||||
function::{ArgumentList, parse_args, validate_pos_params, validate_arguments},
|
||||
context::set_context,
|
||||
string::parse_strings,
|
||||
token::{self, StringKind},
|
||||
@@ -980,17 +980,10 @@ FuncDef: ast::Stmt = {
|
||||
};
|
||||
|
||||
Parameters: ast::Arguments = {
|
||||
<location:@L> "(" <a: (ParameterList<TypedParameter, StarTypedParameter>)?> ")" <end_location:@R> =>? {
|
||||
let args = a.map(validate_arguments).transpose()?.unwrap_or_else(|| ast::Arguments {
|
||||
posonlyargs: vec![],
|
||||
args: vec![],
|
||||
vararg: None,
|
||||
kwonlyargs: vec![],
|
||||
kw_defaults: vec![],
|
||||
kwarg: None,
|
||||
defaults: vec![],
|
||||
range: optional_range(location, end_location)
|
||||
});
|
||||
<location:@L> "(" <a: (ParameterList<TypedParameter, StarTypedParameter, DoubleStarTypedParameter>)?> ")" <end_location:@R> =>? {
|
||||
a.as_ref().map(validate_arguments).transpose()?;
|
||||
let args = a
|
||||
.unwrap_or_else(|| ast::Arguments::empty(optional_range(location, end_location)));
|
||||
|
||||
Ok(args)
|
||||
}
|
||||
@@ -998,12 +991,13 @@ Parameters: ast::Arguments = {
|
||||
|
||||
// Note that this is a macro which is used once for function defs, and
|
||||
// once for lambda defs.
|
||||
ParameterList<ArgType, StarArgType>: ast::Arguments = {
|
||||
<location:@L> <param1:ParameterDefs<ArgType>> <args2:("," <ParameterListStarArgs<ArgType, StarArgType>>)?> ","? <end_location:@R> =>? {
|
||||
let (posonlyargs, args, defaults) = parse_params(param1)?;
|
||||
ParameterList<ArgType, StarArgType, DoubleStarArgType>: ast::Arguments = {
|
||||
<location:@L> <param1:ParameterDefs<ArgType>> <args2:("," <ParameterListStarArgs<ArgType, StarArgType, DoubleStarArgType>>)?> ","? <end_location:@R> =>? {
|
||||
validate_pos_params(¶m1)?;
|
||||
let (posonlyargs, args) = param1;
|
||||
|
||||
// Now gather rest of parameters:
|
||||
let (vararg, kwonlyargs, kw_defaults, kwarg) = args2.unwrap_or((None, vec![], vec![], None));
|
||||
let (vararg, kwonlyargs, kwarg) = args2.unwrap_or((None, vec![], None));
|
||||
|
||||
Ok(ast::Arguments {
|
||||
posonlyargs,
|
||||
@@ -1011,18 +1005,16 @@ ParameterList<ArgType, StarArgType>: ast::Arguments = {
|
||||
kwonlyargs,
|
||||
vararg,
|
||||
kwarg,
|
||||
defaults,
|
||||
kw_defaults,
|
||||
range: optional_range(location, end_location)
|
||||
})
|
||||
},
|
||||
<location:@L> <param1:ParameterDefs<ArgType>> <kw:("," <KwargParameter<ArgType>>)> ","? <end_location:@R> =>? {
|
||||
let (posonlyargs, args, defaults) = parse_params(param1)?;
|
||||
<location:@L> <param1:ParameterDefs<ArgType>> <kw:("," <KwargParameter<DoubleStarArgType>>)> ","? <end_location:@R> =>? {
|
||||
validate_pos_params(¶m1)?;
|
||||
let (posonlyargs, args) = param1;
|
||||
|
||||
// Now gather rest of parameters:
|
||||
let vararg = None;
|
||||
let kwonlyargs = vec![];
|
||||
let kw_defaults = vec![];
|
||||
let kwarg = kw;
|
||||
|
||||
Ok(ast::Arguments {
|
||||
@@ -1031,33 +1023,27 @@ ParameterList<ArgType, StarArgType>: ast::Arguments = {
|
||||
kwonlyargs,
|
||||
vararg,
|
||||
kwarg,
|
||||
defaults,
|
||||
kw_defaults,
|
||||
range: optional_range(location, end_location)
|
||||
})
|
||||
},
|
||||
<location:@L> <params:ParameterListStarArgs<ArgType, StarArgType>> ","? <end_location:@R> => {
|
||||
let (vararg, kwonlyargs, kw_defaults, kwarg) = params;
|
||||
<location:@L> <params:ParameterListStarArgs<ArgType, StarArgType, DoubleStarArgType>> ","? <end_location:@R> => {
|
||||
let (vararg, kwonlyargs, kwarg) = params;
|
||||
ast::Arguments {
|
||||
posonlyargs: vec![],
|
||||
args: vec![],
|
||||
kwonlyargs,
|
||||
vararg,
|
||||
kwarg,
|
||||
defaults: vec![],
|
||||
kw_defaults,
|
||||
range: optional_range(location, end_location)
|
||||
}
|
||||
},
|
||||
<location:@L> <kwarg:KwargParameter<ArgType>> ","? <end_location:@R> => {
|
||||
<location:@L> <kwarg:KwargParameter<DoubleStarArgType>> ","? <end_location:@R> => {
|
||||
ast::Arguments {
|
||||
posonlyargs: vec![],
|
||||
args: vec![],
|
||||
kwonlyargs: vec![],
|
||||
vararg: None,
|
||||
kwarg,
|
||||
defaults: vec![],
|
||||
kw_defaults: vec![],
|
||||
range: optional_range(location, end_location)
|
||||
}
|
||||
},
|
||||
@@ -1065,34 +1051,51 @@ ParameterList<ArgType, StarArgType>: ast::Arguments = {
|
||||
|
||||
// Use inline here to make sure the "," is not creating an ambiguity.
|
||||
#[inline]
|
||||
ParameterDefs<ArgType>: (Vec<(ast::Arg, Option<ast::Expr>)>, Vec<(ast::Arg, Option<ast::Expr>)>) = {
|
||||
ParameterDefs<ArgType>: (Vec<ast::ArgWithDefault>, Vec<ast::ArgWithDefault>) = {
|
||||
<args:OneOrMore<ParameterDef<ArgType>>> => {
|
||||
(vec![], args)
|
||||
},
|
||||
<pos_args:OneOrMore<ParameterDef<ArgType>>> "," "/" <args:("," <ParameterDef<ArgType>>)*> => {
|
||||
(pos_args, args)
|
||||
<posonlyargs:OneOrMore<ParameterDef<ArgType>>> "," "/" <args:("," <ParameterDef<ArgType>>)*> => {
|
||||
(posonlyargs, args)
|
||||
},
|
||||
};
|
||||
|
||||
ParameterDef<ArgType>: (ast::Arg, Option<ast::Expr>) = {
|
||||
<i:ArgType> => (i, None),
|
||||
<i:ArgType> "=" <e:Test<"all">> => (i, Some(e)),
|
||||
ParameterDef<ArgType>: ast::ArgWithDefault = {
|
||||
<i:ArgType> => i,
|
||||
<mut i:ArgType> "=" <e:Test<"all">> => {
|
||||
i.default = Some(Box::new(e));
|
||||
i
|
||||
},
|
||||
};
|
||||
|
||||
UntypedParameter: ast::Arg = {
|
||||
UntypedParameter: ast::ArgWithDefault = {
|
||||
<location:@L> <arg:Identifier> <end_location:@R> => {
|
||||
let def = ast::Arg { arg, annotation: None, type_comment: None, range: (location..end_location).into() };
|
||||
ast::ArgWithDefault { def, default: None, range: optional_range(location, end_location) }
|
||||
},
|
||||
};
|
||||
StarUntypedParameter: ast::Arg = {
|
||||
<location:@L> <arg:Identifier> <end_location:@R> => ast::Arg { arg, annotation: None, type_comment: None, range: (location..end_location).into() },
|
||||
};
|
||||
|
||||
TypedParameter: ast::Arg = {
|
||||
TypedParameter: ast::ArgWithDefault = {
|
||||
<location:@L> <arg:Identifier> <a:(":" <Test<"all">>)?> <end_location:@R> => {
|
||||
let annotation = a.map(|x| Box::new(x));
|
||||
ast::Arg { arg, annotation, type_comment: None, range: (location..end_location).into() }
|
||||
let annotation = a.map(Box::new);
|
||||
let def = ast::Arg { arg, annotation, type_comment: None, range: (location..end_location).into() };
|
||||
ast::ArgWithDefault { def, default: None, range: optional_range(location, end_location) }
|
||||
},
|
||||
};
|
||||
|
||||
StarTypedParameter: ast::Arg = {
|
||||
<location:@L> <arg:Identifier> <a:(":" <TestOrStarExpr>)?> <end_location:@R> => {
|
||||
let annotation = a.map(|x| Box::new(x));
|
||||
let annotation = a.map(Box::new);
|
||||
ast::Arg { arg, annotation, type_comment: None, range: (location..end_location).into() }
|
||||
},
|
||||
};
|
||||
|
||||
DoubleStarTypedParameter: ast::Arg = {
|
||||
<location:@L> <arg:Identifier> <a:(":" <Test<"all">>)?> <end_location:@R> => {
|
||||
let annotation = a.map(Box::new);
|
||||
ast::Arg { arg, annotation, type_comment: None, range: (location..end_location).into() }
|
||||
},
|
||||
};
|
||||
@@ -1100,23 +1103,9 @@ StarTypedParameter: ast::Arg = {
|
||||
// Use inline here to make sure the "," is not creating an ambiguity.
|
||||
// TODO: figure out another grammar that makes this inline no longer required.
|
||||
#[inline]
|
||||
ParameterListStarArgs<ArgType, StarArgType>: (Option<Box<ast::Arg>>, Vec<ast::Arg>, Vec<ast::Expr>, Option<Box<ast::Arg>>) = {
|
||||
<location:@L> "*" <va:StarArgType?> <kw:("," <ParameterDef<ArgType>>)*> <kwarg:("," <KwargParameter<ArgType>>)?> =>? {
|
||||
// Extract keyword arguments:
|
||||
let mut kwonlyargs = Vec::new();
|
||||
let mut kw_defaults = Vec::new();
|
||||
let mut kwargs = Vec::with_capacity(kw.len());
|
||||
for (name, value) in kw {
|
||||
if let Some(value) = value {
|
||||
kwonlyargs.push(name);
|
||||
kw_defaults.push(value);
|
||||
} else {
|
||||
kwargs.push(name);
|
||||
}
|
||||
}
|
||||
kwargs.extend(kwonlyargs.into_iter());
|
||||
|
||||
if va.is_none() && kwargs.is_empty() && kwarg.is_none() {
|
||||
ParameterListStarArgs<ArgType, StarArgType, DoubleStarArgType>: (Option<Box<ast::Arg>>, Vec<ast::ArgWithDefault>, Option<Box<ast::Arg>>) = {
|
||||
<location:@L> "*" <va:StarArgType?> <kwonlyargs:("," <ParameterDef<ArgType>>)*> <kwarg:("," <KwargParameter<DoubleStarArgType>>)?> =>? {
|
||||
if va.is_none() && kwonlyargs.is_empty() && kwarg.is_none() {
|
||||
Err(LexicalError {
|
||||
error: LexicalErrorType::OtherError("named arguments must follow bare *".to_string()),
|
||||
location,
|
||||
@@ -1126,7 +1115,7 @@ ParameterListStarArgs<ArgType, StarArgType>: (Option<Box<ast::Arg>>, Vec<ast::Ar
|
||||
let kwarg = kwarg.flatten();
|
||||
let va = va.map(Box::new);
|
||||
|
||||
Ok((va, kwargs, kw_defaults, kwarg))
|
||||
Ok((va, kwonlyargs, kwarg))
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1205,21 +1194,10 @@ NamedExpression: ast::Expr = {
|
||||
};
|
||||
|
||||
LambdaDef: ast::Expr = {
|
||||
<location:@L> "lambda" <p:ParameterList<UntypedParameter, UntypedParameter>?> ":" <body:Test<"all">> <end_location:@R> =>? {
|
||||
let p = validate_arguments(
|
||||
p.unwrap_or_else(|| {
|
||||
ast::Arguments {
|
||||
posonlyargs: vec![],
|
||||
args: vec![],
|
||||
vararg: None,
|
||||
kwonlyargs: vec![],
|
||||
kw_defaults: vec![],
|
||||
kwarg: None,
|
||||
defaults: vec![],
|
||||
range: optional_range(location, end_location)
|
||||
}
|
||||
}
|
||||
))?;
|
||||
<location:@L> "lambda" <p:ParameterList<UntypedParameter, StarUntypedParameter, StarUntypedParameter>?> ":" <body:Test<"all">> <end_location:@R> =>? {
|
||||
p.as_ref().map(validate_arguments).transpose()?;
|
||||
let p = p
|
||||
.unwrap_or_else(|| ast::Arguments::empty(optional_range(location, end_location)));
|
||||
|
||||
Ok(ast::Expr::Lambda(
|
||||
ast::ExprLambda {
|
||||
|
||||
Reference in New Issue
Block a user