Skip to content

Commit 5f5d36c

Browse files
committed
Make parser no_std compatible
1 parent 313c30c commit 5f5d36c

File tree

11 files changed

+132
-66
lines changed

11 files changed

+132
-66
lines changed

Cargo.lock

Lines changed: 15 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

parser/Cargo.toml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,22 @@ repository = "https://github.com/RustPython/RustPython"
88
license = "MIT"
99
edition = "2018"
1010

11+
[features]
12+
std = []
13+
default = ["std", "lalrpop-util/std", "num-bigint/std"]
14+
1115
[build-dependencies]
12-
lalrpop = "0.19"
16+
lalrpop = "0.19.4"
1317

1418
[dependencies]
1519
rustpython-ast = { path = "../ast" }
16-
lalrpop-util = "0.19.1"
20+
lalrpop-util = { version = "0.19.4", default-features = false }
1721
log = "0.4.1"
18-
num-bigint = "0.3"
19-
num-traits = "0.2"
22+
num-bigint = { version = "0.3", default-features = false }
23+
num-traits = { version = "0.2", default-features = false }
2024
unic-emoji-char = "0.9"
2125
unic-ucd-ident = "0.9"
2226
unicode_names2 = "0.4"
2327
phf = { version = "0.8", features = ["macros"] }
2428
ahash = "0.6"
29+
hashbrown = "0.9"

parser/src/error.rs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ use lalrpop_util::ParseError as LalrpopError;
55
use crate::ast::Location;
66
use crate::token::Tok;
77

8+
use alloc::{boxed::Box, string::String};
9+
use core::fmt;
10+
#[cfg(feature = "std")]
811
use std::error::Error;
9-
use std::fmt;
1012

1113
/// Represents an error during lexical scanning.
1214
#[derive(Debug, PartialEq)]
@@ -70,6 +72,16 @@ impl fmt::Display for LexicalErrorType {
7072
}
7173
}
7274

75+
#[cfg(feature = "std")]
76+
impl Error for LexicalErrorType {
77+
fn source(&self) -> Option<&(dyn Error + 'static)> {
78+
match self {
79+
LexicalErrorType::FStringError(e) => Some(e),
80+
_ => None,
81+
}
82+
}
83+
}
84+
7385
// TODO: consolidate these with ParseError
7486
#[derive(Debug, PartialEq)]
7587
pub struct FStringError {
@@ -119,6 +131,16 @@ impl From<FStringError> for LalrpopError<Location, Tok, LexicalError> {
119131
}
120132
}
121133

134+
#[cfg(feature = "std")]
135+
impl Error for FStringErrorType {
136+
fn source(&self) -> Option<&(dyn Error + 'static)> {
137+
match self {
138+
FStringErrorType::InvalidExpression(e) => Some(e.as_ref()),
139+
_ => None,
140+
}
141+
}
142+
}
143+
122144
/// Represents an error during parsing
123145
#[derive(Debug, PartialEq)]
124146
pub struct ParseError {
@@ -204,14 +226,22 @@ impl fmt::Display for ParseErrorType {
204226
}
205227
}
206228

207-
impl Error for ParseErrorType {}
229+
#[cfg(feature = "std")]
230+
impl Error for ParseErrorType {
231+
fn source(&self) -> Option<&(dyn Error + 'static)> {
232+
match self {
233+
ParseErrorType::Lexical(e) => Some(e),
234+
_ => None,
235+
}
236+
}
237+
}
208238

209239
impl ParseErrorType {
210240
pub fn is_indentation_error(&self) -> bool {
211241
match self {
212242
ParseErrorType::Lexical(LexicalErrorType::IndentationError) => true,
213243
ParseErrorType::UnrecognizedToken(token, expected) => {
214-
*token == Tok::Indent || expected.clone() == Some("Indent".to_owned())
244+
*token == Tok::Indent || expected.as_ref().map_or(false, |s| s == "Indent")
215245
}
216246
_ => false,
217247
}
@@ -225,15 +255,16 @@ impl ParseErrorType {
225255
}
226256
}
227257

228-
impl std::ops::Deref for ParseError {
258+
impl core::ops::Deref for ParseError {
229259
type Target = ParseErrorType;
230260
fn deref(&self) -> &Self::Target {
231261
&self.error
232262
}
233263
}
234264

265+
#[cfg(feature = "std")]
235266
impl Error for ParseError {
236267
fn source(&self) -> Option<&(dyn Error + 'static)> {
237-
None
268+
self.error.source()
238269
}
239270
}

parser/src/fstring.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::iter;
2-
use std::mem;
3-
use std::str;
1+
use alloc::{borrow::ToOwned, boxed::Box, format, string::String, vec, vec::Vec};
2+
use core::{iter, mem, str};
43

54
use crate::ast::{ConversionFlag, Expression, Location, StringGroup};
65
use crate::error::{FStringError, FStringErrorType, ParseError};
@@ -81,7 +80,7 @@ impl<'a> FStringParser<'a> {
8180
// match a python 3.8 self documenting expression
8281
// format '{' PYTHON_EXPRESSION '=' FORMAT_SPECIFIER? '}'
8382
'=' if self.chars.peek() != Some(&'=') && delims.is_empty() => {
84-
pred_expression_text = expression.to_string(); // safe expression before = to print it
83+
pred_expression_text = expression.to_owned(); // safe expression before = to print it
8584
}
8685

8786
':' if delims.is_empty() => {

parser/src/function.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use ahash::RandomState;
2-
use std::collections::HashSet;
1+
use alloc::{string::String, vec, vec::Vec};
2+
use hashbrown::HashSet;
33

44
use crate::ast;
55
use crate::error::{LexicalError, LexicalErrorType};
@@ -46,7 +46,8 @@ pub fn parse_args(func_args: Vec<FunctionArgument>) -> Result<ast::ArgumentList,
4646
let mut args = vec![];
4747
let mut keywords = vec![];
4848

49-
let mut keyword_names = HashSet::with_capacity_and_hasher(func_args.len(), RandomState::new());
49+
let mut keyword_names =
50+
HashSet::with_capacity_and_hasher(func_args.len(), ahash::RandomState::default());
5051
for (name, value) in func_args {
5152
match name {
5253
Some(n) => {

parser/src/lexer.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@
55
pub use super::token::Tok;
66
use crate::ast::Location;
77
use crate::error::{LexicalError, LexicalErrorType};
8+
use alloc::{
9+
borrow::ToOwned,
10+
format,
11+
string::{String, ToString},
12+
vec,
13+
vec::Vec,
14+
};
15+
use core::char;
16+
use core::cmp::Ordering;
17+
use core::str::FromStr;
818
use num_bigint::BigInt;
919
use num_traits::identities::Zero;
1020
use num_traits::Num;
11-
use std::char;
12-
use std::cmp::Ordering;
13-
use std::str::FromStr;
1421
use unic_emoji_char::is_emoji_presentation;
1522
use unic_ucd_ident::{is_xid_continue, is_xid_start};
1623

@@ -436,8 +443,8 @@ where
436443
}
437444
}
438445
match p {
439-
0xD800..=0xDFFF => Ok(std::char::REPLACEMENT_CHARACTER),
440-
_ => std::char::from_u32(p).ok_or(unicode_error),
446+
0xD800..=0xDFFF => Ok(char::REPLACEMENT_CHARACTER),
447+
_ => char::from_u32(p).ok_or(unicode_error),
441448
}
442449
}
443450

parser/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
1818
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
1919
#![doc(html_root_url = "https://docs.rs/rustpython-parser/")]
20+
#![cfg_attr(not(feature = "std"), no_std)]
21+
22+
extern crate alloc;
23+
24+
// hack to get around lalrpop hardcoding ::std::* paths
25+
#[cfg(not(feature = "std"))]
26+
extern crate self as std;
2027

2128
#[macro_use]
2229
extern crate log;

parser/src/mode.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
use core::fmt;
2+
13
#[derive(Clone, Copy)]
24
pub enum Mode {
35
Program,
46
Statement,
57
}
68

7-
impl std::str::FromStr for Mode {
9+
impl core::str::FromStr for Mode {
810
type Err = ModeParseError;
911
fn from_str(s: &str) -> Result<Self, ModeParseError> {
1012
match s {
@@ -20,8 +22,8 @@ pub struct ModeParseError {
2022
_priv: (),
2123
}
2224

23-
impl std::fmt::Display for ModeParseError {
24-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
25+
impl fmt::Display for ModeParseError {
26+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2527
write!(f, r#"mode should be "exec", "eval", or "single""#)
2628
}
2729
}

0 commit comments

Comments
 (0)