forked from Rust-related/RustPython
Compare commits
6 Commits
impl_del_o
...
no_std
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a784d2f0f8 | ||
|
|
bf1e9832f7 | ||
|
|
5f5d36cc74 | ||
|
|
313c30c51b | ||
|
|
d375710650 | ||
|
|
c49cc8f419 |
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -24,6 +24,12 @@ version = "1.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
@@ -876,6 +882,9 @@ name = "hashbrown"
|
|||||||
version = "0.9.1"
|
version = "0.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||||
|
dependencies = [
|
||||||
|
"ahash 0.4.7",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
@@ -1875,7 +1884,7 @@ dependencies = [
|
|||||||
name = "rustpython-compiler-core"
|
name = "rustpython-compiler-core"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash 0.6.2",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"insta",
|
"insta",
|
||||||
"itertools",
|
"itertools",
|
||||||
@@ -1885,6 +1894,7 @@ dependencies = [
|
|||||||
"rustpython-ast",
|
"rustpython-ast",
|
||||||
"rustpython-bytecode",
|
"rustpython-bytecode",
|
||||||
"rustpython-parser",
|
"rustpython-parser",
|
||||||
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1922,7 +1932,8 @@ dependencies = [
|
|||||||
name = "rustpython-parser"
|
name = "rustpython-parser"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash 0.6.2",
|
||||||
|
"hashbrown",
|
||||||
"lalrpop",
|
"lalrpop",
|
||||||
"lalrpop-util",
|
"lalrpop-util",
|
||||||
"log",
|
"log",
|
||||||
@@ -1948,7 +1959,7 @@ name = "rustpython-vm"
|
|||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"adler32",
|
"adler32",
|
||||||
"ahash",
|
"ahash 0.6.2",
|
||||||
"atty",
|
"atty",
|
||||||
"base64",
|
"base64",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
@@ -2233,13 +2244,12 @@ checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.3.17"
|
version = "0.3.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902"
|
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ authors = ["RustPython Team"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num-bigint = "0.3"
|
num-bigint = { version = "0.3", default-features = false }
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
//! location of the node.
|
//! location of the node.
|
||||||
|
|
||||||
pub use crate::location::Location;
|
pub use crate::location::Location;
|
||||||
|
use alloc::{boxed::Box, string::String, vec::Vec};
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
#![no_std]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
mod ast;
|
mod ast;
|
||||||
mod location;
|
mod location;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! Datatypes to support source location information.
|
//! Datatypes to support source location information.
|
||||||
|
|
||||||
use std::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
/// A location somewhere in the sourcecode.
|
/// A location somewhere in the sourcecode.
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||||
|
|||||||
@@ -7,13 +7,16 @@ edition = "2018"
|
|||||||
repository = "https://github.com/RustPython/RustPython"
|
repository = "https://github.com/RustPython/RustPython"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
std = ["bstr/std", "itertools/use_std", "lz4_flex/std"]
|
||||||
|
default = ["std"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bincode = "1.1"
|
bincode = "1.1"
|
||||||
bitflags = "1.1"
|
bitflags = "1.1"
|
||||||
lz4_flex = "0.7"
|
lz4_flex = { version = "0.7", default-features = false, features = ["safe-decode", "safe-encode"] }
|
||||||
num-bigint = { version = "0.3", features = ["serde"] }
|
num-bigint = { version = "0.3", default-features = false, features = ["serde"] }
|
||||||
num-complex = { version = "0.3", features = ["serde"] }
|
num-complex = { version = "0.3", default-features = false, features = ["serde"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
itertools = "0.9"
|
itertools = { version = "0.9", default-features = false }
|
||||||
bstr = "0.2"
|
bstr = { version = "0.2", default-features = false }
|
||||||
|
|||||||
@@ -3,15 +3,19 @@
|
|||||||
|
|
||||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
||||||
#![doc(html_root_url = "https://docs.rs/rustpython-bytecode/")]
|
#![doc(html_root_url = "https://docs.rs/rustpython-bytecode/")]
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use alloc::collections::BTreeSet;
|
||||||
|
use alloc::{borrow::ToOwned, boxed::Box, string::String, vec::Vec};
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use bstr::ByteSlice;
|
use bstr::ByteSlice;
|
||||||
|
use core::fmt;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use num_complex::Complex64;
|
use num_complex::Complex64;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeSet;
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
/// Sourcecode location.
|
/// Sourcecode location.
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||||
@@ -722,6 +726,7 @@ impl fmt::Display for CodeDeserializeError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl std::error::Error for CodeDeserializeError {}
|
impl std::error::Error for CodeDeserializeError {}
|
||||||
|
|
||||||
impl CodeObject<ConstantData> {
|
impl CodeObject<ConstantData> {
|
||||||
|
|||||||
@@ -7,15 +7,20 @@ repository = "https://github.com/RustPython/RustPython"
|
|||||||
license = "MIT"
|
license = "MIT"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
std = ["rustpython-bytecode/std", "itertools/use_std"]
|
||||||
|
default = ["std"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
indexmap = "1.0"
|
indexmap = "1.0"
|
||||||
itertools = "0.9"
|
itertools = { version = "0.9", default-features = false }
|
||||||
rustpython-bytecode = { path = "../bytecode", version = "0.1.1" }
|
rustpython-bytecode = { path = "../bytecode", version = "0.1.1", default-features = false }
|
||||||
rustpython-ast = { path = "../ast" }
|
rustpython-ast = { path = "../ast" }
|
||||||
num-complex = { version = "0.3", features = ["serde"] }
|
num-complex = { version = "0.3", features = ["serde"] }
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
ahash = "0.6"
|
ahash = "0.6"
|
||||||
|
scopeguard = "1.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rustpython-parser = { path = "../parser" }
|
rustpython-parser = { path = "../parser" }
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ description = "A usability wrapper around rustpython-parser and rustpython-compi
|
|||||||
authors = ["RustPython Team"]
|
authors = ["RustPython Team"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
std = ["rustpython-compiler-core/std", "rustpython-bytecode/std", "rustpython-parser/std"]
|
||||||
|
default = ["std"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
rustpython-compiler-core = { path = ".." }
|
rustpython-compiler-core = { path = ".." }
|
||||||
|
|||||||
@@ -10,12 +10,15 @@ use crate::ir::{self, CodeInfo};
|
|||||||
pub use crate::mode::Mode;
|
pub use crate::mode::Mode;
|
||||||
use crate::symboltable::{make_symbol_table, statements_to_symbol_table, SymbolScope, SymbolTable};
|
use crate::symboltable::{make_symbol_table, statements_to_symbol_table, SymbolScope, SymbolTable};
|
||||||
use crate::IndexSet;
|
use crate::IndexSet;
|
||||||
|
use alloc::{borrow::ToOwned, boxed::Box, format, string::String, vec, vec::Vec};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use num_complex::Complex64;
|
use num_complex::Complex64;
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use rustpython_ast as ast;
|
use rustpython_ast as ast;
|
||||||
use rustpython_bytecode::{self as bytecode, CodeObject, ConstantData, Instruction};
|
use rustpython_bytecode::{self as bytecode, CodeObject, ConstantData, Instruction};
|
||||||
|
|
||||||
|
pub use crate::mode::Mode;
|
||||||
|
|
||||||
type CompileResult<T> = Result<T, CompileError>;
|
type CompileResult<T> = Result<T, CompileError>;
|
||||||
|
|
||||||
enum NameUsage {
|
enum NameUsage {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
use rustpython_ast::Location;
|
use rustpython_ast::Location;
|
||||||
|
|
||||||
|
use alloc::string::String;
|
||||||
|
use core::fmt;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CompileError {
|
pub struct CompileError {
|
||||||
@@ -78,6 +80,7 @@ impl fmt::Display for CompileErrorType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Error for CompileErrorType {}
|
impl Error for CompileErrorType {}
|
||||||
|
|
||||||
impl fmt::Display for CompileError {
|
impl fmt::Display for CompileError {
|
||||||
@@ -86,8 +89,5 @@ impl fmt::Display for CompileError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for CompileError {
|
#[cfg(feature = "std")]
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
impl Error for CompileError {}
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
//! Compile a Python AST or source code into bytecode consumable by RustPython.
|
//! Compile a Python AST or source code into bytecode consumable by RustPython.
|
||||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
||||||
#![doc(html_root_url = "https://docs.rs/rustpython-compiler/")]
|
#![doc(html_root_url = "https://docs.rs/rustpython-compiler/")]
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use core::fmt;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
Exec,
|
Exec,
|
||||||
@@ -5,7 +7,7 @@ pub enum Mode {
|
|||||||
Single,
|
Single,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::str::FromStr for Mode {
|
impl core::str::FromStr for Mode {
|
||||||
type Err = ModeParseError;
|
type Err = ModeParseError;
|
||||||
fn from_str(s: &str) -> Result<Self, ModeParseError> {
|
fn from_str(s: &str) -> Result<Self, ModeParseError> {
|
||||||
match s {
|
match s {
|
||||||
@@ -22,8 +24,8 @@ pub struct ModeParseError {
|
|||||||
_priv: (),
|
_priv: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for ModeParseError {
|
impl fmt::Display for ModeParseError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, r#"mode should be "exec", "eval", or "single""#)
|
write!(f, r#"mode should be "exec", "eval", or "single""#)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ Inspirational file: https://github.com/python/cpython/blob/master/Python/symtabl
|
|||||||
|
|
||||||
use crate::error::{CompileError, CompileErrorType};
|
use crate::error::{CompileError, CompileErrorType};
|
||||||
use crate::IndexMap;
|
use crate::IndexMap;
|
||||||
|
use alloc::{borrow::ToOwned, format, string::String, vec, vec::Vec};
|
||||||
|
use core::fmt;
|
||||||
use rustpython_ast::{self as ast, Location};
|
use rustpython_ast::{self as ast, Location};
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
pub fn make_symbol_table(program: &ast::Program) -> Result<SymbolTable, SymbolTableError> {
|
pub fn make_symbol_table(program: &ast::Program) -> Result<SymbolTable, SymbolTableError> {
|
||||||
let mut builder = SymbolTableBuilder::default();
|
let mut builder = SymbolTableBuilder::default();
|
||||||
@@ -187,8 +188,8 @@ impl SymbolTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for SymbolTable {
|
impl fmt::Debug for SymbolTable {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"SymbolTable({:?} symbols, {:?} sub scopes)",
|
"SymbolTable({:?} symbols, {:?} sub scopes)",
|
||||||
@@ -209,8 +210,9 @@ fn analyze_symbol_table(symbol_table: &mut SymbolTable) -> SymbolTableResult {
|
|||||||
type SymbolMap = IndexMap<String, Symbol>;
|
type SymbolMap = IndexMap<String, Symbol>;
|
||||||
|
|
||||||
mod stack {
|
mod stack {
|
||||||
use std::panic;
|
use alloc::vec::Vec;
|
||||||
use std::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
pub struct StackStack<T> {
|
pub struct StackStack<T> {
|
||||||
v: Vec<NonNull<T>>,
|
v: Vec<NonNull<T>>,
|
||||||
}
|
}
|
||||||
@@ -227,9 +229,10 @@ mod stack {
|
|||||||
F: FnOnce(&mut Self) -> R,
|
F: FnOnce(&mut Self) -> R,
|
||||||
{
|
{
|
||||||
self.v.push(x.into());
|
self.v.push(x.into());
|
||||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| f(self)));
|
let mut this = scopeguard::guard(self, |this| {
|
||||||
self.v.pop();
|
this.v.pop();
|
||||||
res.unwrap_or_else(|x| panic::resume_unwind(x))
|
});
|
||||||
|
f(&mut this)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &T> + DoubleEndedIterator + '_ {
|
pub fn iter(&self) -> impl Iterator<Item = &T> + DoubleEndedIterator + '_ {
|
||||||
@@ -273,7 +276,7 @@ struct SymbolTableAnalyzer {
|
|||||||
|
|
||||||
impl SymbolTableAnalyzer {
|
impl SymbolTableAnalyzer {
|
||||||
fn analyze_symbol_table(&mut self, symbol_table: &mut SymbolTable) -> SymbolTableResult {
|
fn analyze_symbol_table(&mut self, symbol_table: &mut SymbolTable) -> SymbolTableResult {
|
||||||
let symbols = std::mem::take(&mut symbol_table.symbols);
|
let symbols = core::mem::take(&mut symbol_table.symbols);
|
||||||
let sub_tables = &mut *symbol_table.sub_tables;
|
let sub_tables = &mut *symbol_table.sub_tables;
|
||||||
|
|
||||||
let mut info = (symbols, symbol_table.typ);
|
let mut info = (symbols, symbol_table.typ);
|
||||||
@@ -469,7 +472,7 @@ impl SymbolTableAnalyzer {
|
|||||||
SymbolTableType::Class => {
|
SymbolTableType::Class => {
|
||||||
// named expressions are forbidden in comprehensions on class scope
|
// named expressions are forbidden in comprehensions on class scope
|
||||||
return Err(SymbolTableError {
|
return Err(SymbolTableError {
|
||||||
error: "assignment expression within a comprehension cannot be used in a class body".to_string(),
|
error: "assignment expression within a comprehension cannot be used in a class body".to_owned(),
|
||||||
// TODO: accurate location info, somehow
|
// TODO: accurate location info, somehow
|
||||||
location: Location::default(),
|
location: Location::default(),
|
||||||
});
|
});
|
||||||
@@ -999,7 +1002,7 @@ impl SymbolTableBuilder {
|
|||||||
// comprehension iterator definitions
|
// comprehension iterator definitions
|
||||||
if let ExpressionContext::IterDefinitionExp = context {
|
if let ExpressionContext::IterDefinitionExp = context {
|
||||||
return Err(SymbolTableError {
|
return Err(SymbolTableError {
|
||||||
error: "assignment expression cannot be used in a comprehension iterable expression".to_string(),
|
error: "assignment expression cannot be used in a comprehension iterable expression".to_owned(),
|
||||||
// TODO: accurate location info, somehow
|
// TODO: accurate location info, somehow
|
||||||
location: Location::default(),
|
location: Location::default(),
|
||||||
});
|
});
|
||||||
@@ -1218,7 +1221,7 @@ impl SymbolTableBuilder {
|
|||||||
return Err(SymbolTableError {
|
return Err(SymbolTableError {
|
||||||
error:
|
error:
|
||||||
"assignment expression cannot be used in a comprehension iterable expression"
|
"assignment expression cannot be used in a comprehension iterable expression"
|
||||||
.to_string(),
|
.to_owned(),
|
||||||
location,
|
location,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,17 +8,22 @@ repository = "https://github.com/RustPython/RustPython"
|
|||||||
license = "MIT"
|
license = "MIT"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
std = []
|
||||||
|
default = ["std", "lalrpop-util/std", "num-bigint/std"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
lalrpop = "0.19"
|
lalrpop = "0.19.4"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rustpython-ast = { path = "../ast" }
|
rustpython-ast = { path = "../ast" }
|
||||||
lalrpop-util = "0.19.1"
|
lalrpop-util = { version = "0.19.4", default-features = false }
|
||||||
log = "0.4.1"
|
log = "0.4.1"
|
||||||
num-bigint = "0.3"
|
num-bigint = { version = "0.3", default-features = false }
|
||||||
num-traits = "0.2"
|
num-traits = { version = "0.2", default-features = false }
|
||||||
unic-emoji-char = "0.9"
|
unic-emoji-char = "0.9"
|
||||||
unic-ucd-ident = "0.9"
|
unic-ucd-ident = "0.9"
|
||||||
unicode_names2 = "0.4"
|
unicode_names2 = "0.4"
|
||||||
phf = { version = "0.8", features = ["macros"] }
|
phf = { version = "0.8", features = ["macros"] }
|
||||||
ahash = "0.6"
|
ahash = "0.6"
|
||||||
|
hashbrown = "0.9"
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ use lalrpop_util::ParseError as LalrpopError;
|
|||||||
use crate::ast::Location;
|
use crate::ast::Location;
|
||||||
use crate::token::Tok;
|
use crate::token::Tok;
|
||||||
|
|
||||||
|
use alloc::{boxed::Box, string::String};
|
||||||
|
use core::fmt;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
/// Represents an error during lexical scanning.
|
/// Represents an error during lexical scanning.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@@ -70,6 +72,16 @@ impl fmt::Display for LexicalErrorType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl Error for LexicalErrorType {
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
LexicalErrorType::FStringError(e) => Some(e),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: consolidate these with ParseError
|
// TODO: consolidate these with ParseError
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct FStringError {
|
pub struct FStringError {
|
||||||
@@ -119,6 +131,16 @@ impl From<FStringError> for LalrpopError<Location, Tok, LexicalError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl Error for FStringErrorType {
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
FStringErrorType::InvalidExpression(e) => Some(e.as_ref()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents an error during parsing
|
/// Represents an error during parsing
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct ParseError {
|
pub struct ParseError {
|
||||||
@@ -204,14 +226,22 @@ impl fmt::Display for ParseErrorType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for ParseErrorType {}
|
#[cfg(feature = "std")]
|
||||||
|
impl Error for ParseErrorType {
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
ParseErrorType::Lexical(e) => Some(e),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ParseErrorType {
|
impl ParseErrorType {
|
||||||
pub fn is_indentation_error(&self) -> bool {
|
pub fn is_indentation_error(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
ParseErrorType::Lexical(LexicalErrorType::IndentationError) => true,
|
ParseErrorType::Lexical(LexicalErrorType::IndentationError) => true,
|
||||||
ParseErrorType::UnrecognizedToken(token, expected) => {
|
ParseErrorType::UnrecognizedToken(token, expected) => {
|
||||||
*token == Tok::Indent || expected.clone() == Some("Indent".to_owned())
|
*token == Tok::Indent || expected.as_ref().map_or(false, |s| s == "Indent")
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
@@ -225,15 +255,16 @@ impl ParseErrorType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Deref for ParseError {
|
impl core::ops::Deref for ParseError {
|
||||||
type Target = ParseErrorType;
|
type Target = ParseErrorType;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.error
|
&self.error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Error for ParseError {
|
impl Error for ParseError {
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
None
|
self.error.source()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use std::iter;
|
use alloc::{borrow::ToOwned, boxed::Box, format, string::String, vec, vec::Vec};
|
||||||
use std::mem;
|
use core::{iter, mem, str};
|
||||||
use std::str;
|
|
||||||
|
|
||||||
use crate::ast::{ConversionFlag, Expression, Location, StringGroup};
|
use crate::ast::{ConversionFlag, Expression, Location, StringGroup};
|
||||||
use crate::error::{FStringError, FStringErrorType, ParseError};
|
use crate::error::{FStringError, FStringErrorType, ParseError};
|
||||||
@@ -81,7 +80,7 @@ impl<'a> FStringParser<'a> {
|
|||||||
// match a python 3.8 self documenting expression
|
// match a python 3.8 self documenting expression
|
||||||
// format '{' PYTHON_EXPRESSION '=' FORMAT_SPECIFIER? '}'
|
// format '{' PYTHON_EXPRESSION '=' FORMAT_SPECIFIER? '}'
|
||||||
'=' if self.chars.peek() != Some(&'=') && delims.is_empty() => {
|
'=' if self.chars.peek() != Some(&'=') && delims.is_empty() => {
|
||||||
pred_expression_text = expression.to_string(); // safe expression before = to print it
|
pred_expression_text = expression.to_owned(); // safe expression before = to print it
|
||||||
}
|
}
|
||||||
|
|
||||||
':' if delims.is_empty() => {
|
':' if delims.is_empty() => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use ahash::RandomState;
|
use alloc::{string::String, vec, vec::Vec};
|
||||||
use std::collections::HashSet;
|
use hashbrown::HashSet;
|
||||||
|
|
||||||
use crate::ast;
|
use crate::ast;
|
||||||
use crate::error::{LexicalError, LexicalErrorType};
|
use crate::error::{LexicalError, LexicalErrorType};
|
||||||
@@ -46,7 +46,8 @@ pub fn parse_args(func_args: Vec<FunctionArgument>) -> Result<ast::ArgumentList,
|
|||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
let mut keywords = vec![];
|
let mut keywords = vec![];
|
||||||
|
|
||||||
let mut keyword_names = HashSet::with_capacity_and_hasher(func_args.len(), RandomState::new());
|
let mut keyword_names =
|
||||||
|
HashSet::with_capacity_and_hasher(func_args.len(), ahash::RandomState::default());
|
||||||
for (name, value) in func_args {
|
for (name, value) in func_args {
|
||||||
match name {
|
match name {
|
||||||
Some(n) => {
|
Some(n) => {
|
||||||
|
|||||||
@@ -5,12 +5,19 @@
|
|||||||
pub use super::token::Tok;
|
pub use super::token::Tok;
|
||||||
use crate::ast::Location;
|
use crate::ast::Location;
|
||||||
use crate::error::{LexicalError, LexicalErrorType};
|
use crate::error::{LexicalError, LexicalErrorType};
|
||||||
|
use alloc::{
|
||||||
|
borrow::ToOwned,
|
||||||
|
format,
|
||||||
|
string::{String, ToString},
|
||||||
|
vec,
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
use core::char;
|
||||||
|
use core::cmp::Ordering;
|
||||||
|
use core::str::FromStr;
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use num_traits::identities::Zero;
|
use num_traits::identities::Zero;
|
||||||
use num_traits::Num;
|
use num_traits::Num;
|
||||||
use std::char;
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use unic_emoji_char::is_emoji_presentation;
|
use unic_emoji_char::is_emoji_presentation;
|
||||||
use unic_ucd_ident::{is_xid_continue, is_xid_start};
|
use unic_ucd_ident::{is_xid_continue, is_xid_start};
|
||||||
|
|
||||||
@@ -436,8 +443,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
match p {
|
match p {
|
||||||
0xD800..=0xDFFF => Ok(std::char::REPLACEMENT_CHARACTER),
|
0xD800..=0xDFFF => Ok(char::REPLACEMENT_CHARACTER),
|
||||||
_ => std::char::from_u32(p).ok_or(unicode_error),
|
_ => char::from_u32(p).ok_or(unicode_error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,13 @@
|
|||||||
|
|
||||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
||||||
#![doc(html_root_url = "https://docs.rs/rustpython-parser/")]
|
#![doc(html_root_url = "https://docs.rs/rustpython-parser/")]
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
// hack to get around lalrpop hardcoding ::std::* paths
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
extern crate self as std;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
use core::fmt;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
Program,
|
Program,
|
||||||
Statement,
|
Statement,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::str::FromStr for Mode {
|
impl core::str::FromStr for Mode {
|
||||||
type Err = ModeParseError;
|
type Err = ModeParseError;
|
||||||
fn from_str(s: &str) -> Result<Self, ModeParseError> {
|
fn from_str(s: &str) -> Result<Self, ModeParseError> {
|
||||||
match s {
|
match s {
|
||||||
@@ -20,8 +22,8 @@ pub struct ModeParseError {
|
|||||||
_priv: (),
|
_priv: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for ModeParseError {
|
impl fmt::Display for ModeParseError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, r#"mode should be "exec", "eval", or "single""#)
|
write!(f, r#"mode should be "exec", "eval", or "single""#)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
//! parse a whole program, a single statement, or a single
|
//! parse a whole program, a single statement, or a single
|
||||||
//! expression.
|
//! expression.
|
||||||
|
|
||||||
use std::iter;
|
use alloc::vec::Vec;
|
||||||
|
use core::iter;
|
||||||
|
|
||||||
use crate::ast;
|
use crate::ast;
|
||||||
use crate::error::ParseError;
|
use crate::error::ParseError;
|
||||||
@@ -106,6 +107,7 @@ mod tests {
|
|||||||
use super::parse_expression;
|
use super::parse_expression;
|
||||||
use super::parse_program;
|
use super::parse_program;
|
||||||
use super::parse_statement;
|
use super::parse_statement;
|
||||||
|
use alloc::borrow::ToOwned;
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
|
|
||||||
fn mk_ident(name: &str, row: usize, col: usize) -> ast::Expression {
|
fn mk_ident(name: &str, row: usize, col: usize) -> ast::Expression {
|
||||||
@@ -136,7 +138,7 @@ mod tests {
|
|||||||
custom: (),
|
custom: (),
|
||||||
node: ast::ExpressionType::String {
|
node: ast::ExpressionType::String {
|
||||||
value: ast::StringGroup::Constant {
|
value: ast::StringGroup::Constant {
|
||||||
value: String::from(value),
|
value: value.to_owned(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -158,8 +160,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_print_hello() {
|
fn test_parse_print_hello() {
|
||||||
let source = String::from("print('Hello world')");
|
let source = "print('Hello world')";
|
||||||
let parse_ast = parse_program(&source).unwrap();
|
let parse_ast = parse_program(source).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_ast,
|
parse_ast,
|
||||||
ast::Program {
|
ast::Program {
|
||||||
@@ -184,8 +186,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_print_2() {
|
fn test_parse_print_2() {
|
||||||
let source = String::from("print('Hello world', 2)");
|
let source = "print('Hello world', 2)";
|
||||||
let parse_ast = parse_program(&source).unwrap();
|
let parse_ast = parse_program(source).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_ast,
|
parse_ast,
|
||||||
ast::Program {
|
ast::Program {
|
||||||
@@ -210,8 +212,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_kwargs() {
|
fn test_parse_kwargs() {
|
||||||
let source = String::from("my_func('positional', keyword=2)");
|
let source = "my_func('positional', keyword=2)";
|
||||||
let parse_ast = parse_program(&source).unwrap();
|
let parse_ast = parse_program(source).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_ast,
|
parse_ast,
|
||||||
ast::Program {
|
ast::Program {
|
||||||
@@ -239,8 +241,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_if_elif_else() {
|
fn test_parse_if_elif_else() {
|
||||||
let source = String::from("if 1: 10\nelif 2: 20\nelse: 30");
|
let source = "if 1: 10\nelif 2: 20\nelse: 30";
|
||||||
let parse_ast = parse_statement(&source).unwrap();
|
let parse_ast = parse_statement(source).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_ast,
|
parse_ast,
|
||||||
vec![ast::Statement {
|
vec![ast::Statement {
|
||||||
@@ -265,8 +267,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_lambda() {
|
fn test_parse_lambda() {
|
||||||
let source = String::from("lambda x, y: x * y"); // lambda(x, y): x * y");
|
let source = "lambda x, y: x * y"; // lambda(x, y): x * y");
|
||||||
let parse_ast = parse_statement(&source);
|
let parse_ast = parse_statement(source);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_ast,
|
parse_ast,
|
||||||
Ok(vec![as_statement(ast::Expression {
|
Ok(vec![as_statement(ast::Expression {
|
||||||
@@ -278,12 +280,12 @@ mod tests {
|
|||||||
args: vec![
|
args: vec![
|
||||||
ast::Parameter {
|
ast::Parameter {
|
||||||
location: ast::Location::new(1, 8),
|
location: ast::Location::new(1, 8),
|
||||||
arg: String::from("x"),
|
arg: "x".to_owned(),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
},
|
},
|
||||||
ast::Parameter {
|
ast::Parameter {
|
||||||
location: ast::Location::new(1, 11),
|
location: ast::Location::new(1, 11),
|
||||||
arg: String::from("y"),
|
arg: "y".to_owned(),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -309,10 +311,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_tuples() {
|
fn test_parse_tuples() {
|
||||||
let source = String::from("a, b = 4, 5");
|
let source = "a, b = 4, 5";
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_statement(&source),
|
parse_statement(source),
|
||||||
Ok(vec![ast::Statement {
|
Ok(vec![ast::Statement {
|
||||||
location: ast::Location::new(1, 1),
|
location: ast::Location::new(1, 1),
|
||||||
custom: (),
|
custom: (),
|
||||||
@@ -338,16 +340,19 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_class() {
|
fn test_parse_class() {
|
||||||
let source = String::from(
|
let source = "\
|
||||||
"class Foo(A, B):\n def __init__(self):\n pass\n def method_with_default(self, arg='default'):\n pass",
|
class Foo(A, B):
|
||||||
);
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
def method_with_default(self, arg='default'):
|
||||||
|
pass";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_statement(&source),
|
parse_statement(source),
|
||||||
Ok(vec![ast::Statement {
|
Ok(vec![ast::Statement {
|
||||||
location: ast::Location::new(1, 1),
|
location: ast::Location::new(1, 1),
|
||||||
custom: (),
|
custom: (),
|
||||||
node: ast::StatementType::ClassDef {
|
node: ast::StatementType::ClassDef {
|
||||||
name: String::from("Foo"),
|
name: "Foo".to_owned(),
|
||||||
bases: vec![mk_ident("A", 1, 11), mk_ident("B", 1, 14)],
|
bases: vec![mk_ident("A", 1, 11), mk_ident("B", 1, 14)],
|
||||||
keywords: vec![],
|
keywords: vec![],
|
||||||
body: vec![
|
body: vec![
|
||||||
@@ -356,12 +361,12 @@ mod tests {
|
|||||||
custom: (),
|
custom: (),
|
||||||
node: ast::StatementType::FunctionDef {
|
node: ast::StatementType::FunctionDef {
|
||||||
is_async: false,
|
is_async: false,
|
||||||
name: String::from("__init__"),
|
name: "__init__".to_owned(),
|
||||||
args: Box::new(ast::Parameters {
|
args: Box::new(ast::Parameters {
|
||||||
posonlyargs_count: 0,
|
posonlyargs_count: 0,
|
||||||
args: vec![ast::Parameter {
|
args: vec![ast::Parameter {
|
||||||
location: ast::Location::new(2, 15),
|
location: ast::Location::new(2, 15),
|
||||||
arg: String::from("self"),
|
arg: "self".to_owned(),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
}],
|
}],
|
||||||
kwonlyargs: vec![],
|
kwonlyargs: vec![],
|
||||||
@@ -384,18 +389,18 @@ mod tests {
|
|||||||
custom: (),
|
custom: (),
|
||||||
node: ast::StatementType::FunctionDef {
|
node: ast::StatementType::FunctionDef {
|
||||||
is_async: false,
|
is_async: false,
|
||||||
name: String::from("method_with_default"),
|
name: "method_with_default".to_owned(),
|
||||||
args: Box::new(ast::Parameters {
|
args: Box::new(ast::Parameters {
|
||||||
posonlyargs_count: 0,
|
posonlyargs_count: 0,
|
||||||
args: vec![
|
args: vec![
|
||||||
ast::Parameter {
|
ast::Parameter {
|
||||||
location: ast::Location::new(4, 26),
|
location: ast::Location::new(4, 26),
|
||||||
arg: String::from("self"),
|
arg: "self".to_owned(),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
},
|
},
|
||||||
ast::Parameter {
|
ast::Parameter {
|
||||||
location: ast::Location::new(4, 32),
|
location: ast::Location::new(4, 32),
|
||||||
arg: String::from("arg"),
|
arg: "arg".to_owned(),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -423,8 +428,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_dict_comprehension() {
|
fn test_parse_dict_comprehension() {
|
||||||
let source = String::from("{x1: x2 for y in z}");
|
let source = "{x1: x2 for y in z}";
|
||||||
let parse_ast = parse_expression(&source).unwrap();
|
let parse_ast = parse_expression(source).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_ast,
|
parse_ast,
|
||||||
ast::Expression {
|
ast::Expression {
|
||||||
@@ -449,8 +454,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_list_comprehension() {
|
fn test_parse_list_comprehension() {
|
||||||
let source = String::from("[x for y in z]");
|
let source = "[x for y in z]";
|
||||||
let parse_ast = parse_expression(&source).unwrap();
|
let parse_ast = parse_expression(source).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_ast,
|
parse_ast,
|
||||||
ast::Expression {
|
ast::Expression {
|
||||||
@@ -474,8 +479,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_double_list_comprehension() {
|
fn test_parse_double_list_comprehension() {
|
||||||
let source = String::from("[x for y, y2 in z for a in b if a < 5 if a > 10]");
|
let source = "[x for y, y2 in z for a in b if a < 5 if a > 10]";
|
||||||
let parse_ast = parse_expression(&source).unwrap();
|
let parse_ast = parse_expression(source).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_ast,
|
parse_ast,
|
||||||
ast::Expression {
|
ast::Expression {
|
||||||
|
|||||||
@@ -3,13 +3,12 @@
|
|||||||
// See also: file:///usr/share/doc/python/html/reference/compound_stmts.html#function-definitions
|
// See also: file:///usr/share/doc/python/html/reference/compound_stmts.html#function-definitions
|
||||||
// See also: https://greentreesnakes.readthedocs.io/en/latest/nodes.html#keyword
|
// See also: https://greentreesnakes.readthedocs.io/en/latest/nodes.html#keyword
|
||||||
|
|
||||||
use std::iter::FromIterator;
|
|
||||||
|
|
||||||
use crate::ast;
|
use crate::ast;
|
||||||
use crate::fstring::parse_located_fstring;
|
use crate::fstring::parse_located_fstring;
|
||||||
use crate::function::{parse_args, parse_params};
|
use crate::function::{parse_args, parse_params};
|
||||||
use crate::error::LexicalError;
|
use crate::error::LexicalError;
|
||||||
use crate::lexer;
|
use crate::lexer;
|
||||||
|
use alloc::{boxed::Box, string::{String, ToString}, vec, vec::Vec};
|
||||||
|
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
|
|
||||||
@@ -26,7 +25,7 @@ pub Top: ast::Top = {
|
|||||||
|
|
||||||
Program: ast::Program = {
|
Program: ast::Program = {
|
||||||
<lines:FileLine*> => ast::Program {
|
<lines:FileLine*> => ast::Program {
|
||||||
statements: Vec::from_iter(lines.into_iter().flatten())
|
statements: lines.into_iter().flatten().collect(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
//! Different token definitions.
|
//! Different token definitions.
|
||||||
//! Loosely based on token.h from CPython source:
|
//! Loosely based on token.h from CPython source:
|
||||||
|
use alloc::{string::String, vec::Vec};
|
||||||
|
use core::fmt::{self, Write};
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use std::fmt::{self, Write};
|
|
||||||
|
|
||||||
/// Python source code can be tokenized in a sequence of these tokens.
|
/// Python source code can be tokenized in a sequence of these tokens.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
|||||||
@@ -9,13 +9,14 @@ edition = "2018"
|
|||||||
include = ["src/**/*.rs", "Cargo.toml", "build.rs", "Lib/**/*.py"]
|
include = ["src/**/*.rs", "Cargo.toml", "build.rs", "Lib/**/*.py"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["compile-parse", "threading"]
|
default = ["compile-parse", "threading", "std"]
|
||||||
vm-tracing-logging = []
|
vm-tracing-logging = []
|
||||||
flame-it = ["flame", "flamer"]
|
flame-it = ["flame", "flamer"]
|
||||||
freeze-stdlib = ["rustpython-pylib"]
|
freeze-stdlib = ["rustpython-pylib"]
|
||||||
jit = ["rustpython-jit"]
|
jit = ["rustpython-jit"]
|
||||||
threading = ["rustpython-common/threading"]
|
threading = ["rustpython-common/threading"]
|
||||||
compile-parse = ["rustpython-parser", "rustpython-compiler"]
|
compile-parse = ["rustpython-parser", "rustpython-compiler"]
|
||||||
|
std = ["rustpython-compiler/std"] # enables compiler-core/std, parser/std, etc
|
||||||
|
|
||||||
ssl = ["openssl", "openssl-sys", "openssl-probe"]
|
ssl = ["openssl", "openssl-sys", "openssl-probe"]
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#![allow(clippy::module_inception)]
|
#![allow(clippy::module_inception)]
|
||||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
||||||
#![doc(html_root_url = "https://docs.rs/rustpython-vm/")]
|
#![doc(html_root_url = "https://docs.rs/rustpython-vm/")]
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
#[cfg(feature = "flame-it")]
|
#[cfg(feature = "flame-it")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|||||||
Reference in New Issue
Block a user