forked from Rust-related/RustPython
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -220,9 +220,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.6"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1159,7 +1160,7 @@ dependencies = [
|
||||
"blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"caseless 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1209,6 +1210,7 @@ dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode_names2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasm-bindgen 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wtf8 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -2033,7 +2035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum caseless 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "808dab3318747be122cb31d36de18d4d1c81277a76f8332a02b81a3d73463d7f"
|
||||
"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be"
|
||||
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
|
||||
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
|
||||
"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe"
|
||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120"
|
||||
|
||||
@@ -321,6 +321,12 @@ pub struct Comprehension {
|
||||
pub is_async: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ArgumentList {
|
||||
pub args: Vec<Expression>,
|
||||
pub keywords: Vec<Keyword>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Keyword {
|
||||
pub name: Option<String>,
|
||||
|
||||
@@ -20,6 +20,7 @@ pub enum LexicalErrorType {
|
||||
StringError,
|
||||
UnicodeError,
|
||||
NestingError,
|
||||
PositionalArgumentError,
|
||||
UnrecognizedToken { tok: char },
|
||||
FStringError(FStringErrorType),
|
||||
OtherError(String),
|
||||
@@ -32,6 +33,9 @@ impl fmt::Display for LexicalErrorType {
|
||||
LexicalErrorType::FStringError(error) => write!(f, "Got error in f-string: {}", error),
|
||||
LexicalErrorType::UnicodeError => write!(f, "Got unexpected unicode"),
|
||||
LexicalErrorType::NestingError => write!(f, "Got unexpected nesting"),
|
||||
LexicalErrorType::PositionalArgumentError => {
|
||||
write!(f, "positional argument follows keyword argument")
|
||||
}
|
||||
LexicalErrorType::UnrecognizedToken { tok } => {
|
||||
write!(f, "Got unexpected token {}", tok)
|
||||
}
|
||||
@@ -40,6 +44,12 @@ impl fmt::Display for LexicalErrorType {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LexicalError> for LalrpopError<Location, Tok, LexicalError> {
|
||||
fn from(err: LexicalError) -> Self {
|
||||
lalrpop_util::ParseError::User { error: err }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: consolidate these with ParseError
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct FStringError {
|
||||
|
||||
36
parser/src/function.rs
Normal file
36
parser/src/function.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use crate::ast;
|
||||
use crate::error::{LexicalError, LexicalErrorType};
|
||||
|
||||
type FunctionArgument = (Option<Option<String>>, ast::Expression);
|
||||
|
||||
pub fn parse_args(func_args: Vec<FunctionArgument>) -> Result<ast::ArgumentList, LexicalError> {
|
||||
let mut args = vec![];
|
||||
let mut keywords = vec![];
|
||||
for (name, value) in func_args {
|
||||
match name {
|
||||
Some(n) => {
|
||||
keywords.push(ast::Keyword { name: n, value });
|
||||
}
|
||||
None => {
|
||||
// Allow starred args after keyword arguments.
|
||||
if !keywords.is_empty() && !is_starred(&value) {
|
||||
return Err(LexicalError {
|
||||
error: LexicalErrorType::PositionalArgumentError,
|
||||
location: value.location.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
args.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(ast::ArgumentList { args, keywords })
|
||||
}
|
||||
|
||||
fn is_starred(exp: &ast::Expression) -> bool {
|
||||
if let ast::ExpressionType::Starred { .. } = exp.node {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ use lalrpop_util::lalrpop_mod;
|
||||
pub mod ast;
|
||||
pub mod error;
|
||||
mod fstring;
|
||||
mod function;
|
||||
pub mod lexer;
|
||||
pub mod location;
|
||||
pub mod parser;
|
||||
|
||||
@@ -7,6 +7,7 @@ use std::iter::FromIterator;
|
||||
|
||||
use crate::ast;
|
||||
use crate::fstring::parse_located_fstring;
|
||||
use crate::function::parse_args;
|
||||
use crate::error::LexicalError;
|
||||
use crate::lexer;
|
||||
use crate::location;
|
||||
@@ -580,7 +581,7 @@ KwargParameter<ArgType>: Option<ast::Parameter> = {
|
||||
ClassDef: ast::Statement = {
|
||||
<decorator_list:Decorator*> <location:@L> "class" <name:Identifier> <a:("(" ArgumentList ")")?> ":" <body:Suite> => {
|
||||
let (bases, keywords) = match a {
|
||||
Some((_, args, _)) => args,
|
||||
Some((_, arg, _)) => (arg.args, arg.keywords),
|
||||
None => (vec![], vec![]),
|
||||
};
|
||||
ast::Statement {
|
||||
@@ -616,14 +617,13 @@ Path: ast::Expression = {
|
||||
Decorator: ast::Expression = {
|
||||
"@" <p:Path> <a: (@L "(" ArgumentList ")")?> "\n" => {
|
||||
match a {
|
||||
Some((location, _, args, _)) => {
|
||||
let (args, keywords) = args;
|
||||
Some((location, _, arg, _)) => {
|
||||
ast::Expression {
|
||||
location,
|
||||
node: ast::ExpressionType::Call {
|
||||
function: Box::new(p),
|
||||
args,
|
||||
keywords,
|
||||
args: arg.args,
|
||||
keywords: arg.keywords,
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -633,7 +633,7 @@ Decorator: ast::Expression = {
|
||||
};
|
||||
|
||||
YieldExpr: ast::Expression = {
|
||||
<location:@L> "yield" <value:TestList?> => ast::Expression {
|
||||
<location:@L> "yield" <value:TestList?> => ast::Expression {
|
||||
location,
|
||||
node: ast::ExpressionType::Yield { value: value.map(Box::new) }
|
||||
},
|
||||
@@ -847,10 +847,9 @@ AtomExpr: ast::Expression = {
|
||||
AtomExpr2: ast::Expression = {
|
||||
Atom,
|
||||
<f:AtomExpr2> <location:@L> "(" <a:ArgumentList> ")" => {
|
||||
let (args, keywords) = a;
|
||||
ast::Expression {
|
||||
location,
|
||||
node: ast::ExpressionType::Call { function: Box::new(f), args, keywords }
|
||||
node: ast::ExpressionType::Call { function: Box::new(f), args: a.args, keywords: a.keywords }
|
||||
}
|
||||
},
|
||||
<e:AtomExpr2> <location:@L> "[" <s:SubscriptList> "]" => ast::Expression {
|
||||
@@ -1060,31 +1059,10 @@ SingleForComprehension: ast::Comprehension = {
|
||||
ExpressionNoCond: ast::Expression = OrTest;
|
||||
ComprehensionIf: ast::Expression = "if" <c:ExpressionNoCond> => c;
|
||||
|
||||
ArgumentList: (Vec<ast::Expression>, Vec<ast::Keyword>) = {
|
||||
<e: Comma<FunctionArgument>> => {
|
||||
let mut args = vec![];
|
||||
let mut keywords = vec![];
|
||||
for (name, value) in e {
|
||||
match name {
|
||||
Some(n) => {
|
||||
keywords.push(ast::Keyword { name: n, value: value });
|
||||
},
|
||||
None => {
|
||||
// Allow starred args after keyword arguments.
|
||||
let is_starred = if let ast::ExpressionType::Starred { .. } = &value.node {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if keywords.len() > 0 && !is_starred {
|
||||
panic!("positional argument follows keyword argument {:?}", keywords);
|
||||
};
|
||||
args.push(value);
|
||||
},
|
||||
}
|
||||
}
|
||||
(args, keywords)
|
||||
ArgumentList: ast::ArgumentList = {
|
||||
<e: Comma<FunctionArgument>> =>? {
|
||||
let arg_list = parse_args(e)?;
|
||||
Ok(arg_list)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
from testutils import assertRaises
|
||||
|
||||
|
||||
__name__ = "function"
|
||||
|
||||
|
||||
@@ -88,3 +91,7 @@ def f8() -> int:
|
||||
return 10
|
||||
|
||||
assert f8() == 10
|
||||
|
||||
|
||||
with assertRaises(SyntaxError):
|
||||
exec('print(keyword=10, 20)')
|
||||
|
||||
Reference in New Issue
Block a user