Repository: pest-parser/pest (language: rust)

Issue:
No std? 
I assume this doesn't support no std. What work needs to be done to make it support it? I would be happy to do it with direction. 



Discussion / hints:
This is an interesting feature and I'm up for putting this under a compilation flag, or even making it completely std-free.

Off the top of my head, these are the few things that might not be available in core:

* Procedural macros (which are mandatory; there's no way to replace this)
* pest's few depedencies (might be possible to open PRs)
* `Iterator` usage in `Pairs`

Happy to seea PR with this in case it proves feasible.
Are procedural macros not available in core? We'll have to check this. Iterators are all fine, and dependencies should be able to be ported. 
@dragostis killercup says that proc macros should be fine as long as they don't generate code that is no std
Then, it might be possible. The derive might be a bit more complicated since it uses collections and boxes, but I do not necessarily think that having derive be no std is a good idea, since it's supposed to have access to higher level constructs. Same goes for meta. However, cargo's reliance on building everything from source might be an issue here.
Collections are fine, we can get most of those from `alloc`. 
I see. It's worth a shot. Is there any reason why meta and derive should also be no std? I envision a future where these crates will be mere binaries downloaded for code-generation purposes. However, the current situation is different and I see no significant progress in this direction.
I don't know what meta and derive do, but derive seems like it's just a derive macro, so it shouldn't need nostd. 
Meta basically parses the pest grammar and does optomizations. It's part of the whole code generation process that the user should not see.
If it only generates code then probably not. All code generated/all code included (as library code) needs to be no std iirc. 
I guess I'm confused as to what's the drive for no std? I mean, there's a wonderful std included with rust. Seems a shame not to use it? Are you looking to do some heavy parsing on embedded devices or as part of an OS kernel?
Yes. I want to use pest to parse AML for the acpi library (rust-osdev/acpi). It's not a thing of "we should use it because it's nice", it's a thing of it being better to be versatile by using the smallest subset of the stdlib possible (core is just useful stuff like iterators, alloc is heap things, and std is both but with OS functions) to be portable. Most of std is re-exported from core, anyway, such as iterators, from, try from, closures, all the nice traits, etc. Essentially, std = core + alloc + os functions, so core = std - alloc - os functions, which is basically all of the nice stuff in the stdlib anyway :smiley:
So I guess the idea is grab the dependencies from core + alloc + proc_macro specifically?  That should be fine. Especially since, fairly recently, we're no longer depending on OS functionality from libc.
Yeah, exactly. 
Started on this [here](https://github.com/Restioson/pest/tree/no_std). Derive macro works and is ported! Tested on some grammar I found in the book:
```
field = { ('0'..'9' | "." | "-")+ }
```
So this might be a dumb question, but why wouldn't you want to just use the non-std imports all the time? Especially since it seems that std is just re-exporting the names from their underlying modules?
@jstnelf for the derive macros we can't, since core and alloc aren't available in std builds (so we'd get an undefined reference).  For the other crates we can. 
@jstnlef actually in general we can't, since no std requires nightly (alloc is unstable, etc).
I've mad a bit more progress on this. So far the only thing I've run into is that all the stuff from `alloc` isn't in the prelude anymore, so what's needed has to be `use`'d in ever file. This could be a bit annoying to maintain, perhaps? Any ideas? I wish [this](https://github.com/rust-lang/rfcs/pull/890) was merged...
![Tada](https://i.imgur.com/OlfdKy8.png)
@Restioson That's fine. I actually don't have a lot of experience with running Rust in an non-std env so I would defer to your judgement.
Could you maybe make a module that `pub use`s all the stuff you need from `alloc`, which you could then include conditionally? Bit messy, but it should work
I have that in `mod std`? Basically it's a facade that looks and feels like std.

I've tentatively marked this as abandoned. If anyone is curious to give this a try, let me know.
Not gonna lie, I completely forgot about this. I can try do more work on this probably soon.
Hi, one year later: I’d still be interested in this :smile: 

Fix patch:
diff --git a/pest/Cargo.toml b/pest/Cargo.toml
index 636448ba..def9da82 100644
--- a/pest/Cargo.toml
+++ b/pest/Cargo.toml
@@ -12,6 +12,9 @@ license = "MIT/Apache-2.0"
 readme = "_README.md"
 
 [features]
+default = ["std"]
+# Implements `std::error::Error` for the `Error` type
+std = []
 # Enables the `to_json` function for `Pair` and `Pairs`
 pretty-print = ["serde", "serde_json"]
 # Enable const fn constructor for `PrecClimber` (requires nightly)
diff --git a/pest/src/error.rs b/pest/src/error.rs
index bd9da76f..8c01cefd 100644
--- a/pest/src/error.rs
+++ b/pest/src/error.rs
@@ -9,11 +9,15 @@
 
 //! Types for different kinds of parsing failures.
 
-use std::borrow::Cow;
-use std::cmp;
-use std::error;
-use std::fmt;
-use std::mem;
+use alloc::borrow::Cow;
+use alloc::borrow::ToOwned;
+use alloc::format;
+use alloc::string::String;
+use alloc::string::ToString;
+use alloc::vec::Vec;
+use core::cmp;
+use core::fmt;
+use core::mem;
 
 use position::Position;
 use span::Span;
@@ -468,7 +472,8 @@ impl<R: RuleType> fmt::Display for Error<R> {
     }
 }
 
-impl<'i, R: RuleType> error::Error for Error<R> {
+#[cfg(feature = "std")]
+impl<'i, R: RuleType> std::error::Error for Error<R> {
     fn description(&self) -> &str {
         match self.variant {
             ErrorVariant::ParsingError { .. } => "parsing error",
@@ -485,6 +490,7 @@ fn visualize_whitespace(input: &str) -> String {
 mod tests {
     use super::super::position;
     use super::*;
+    use alloc::vec;
 
     #[test]
     fn display_parsing_error_mixed() {
diff --git a/pest/src/iterators/flat_pairs.rs b/pest/src/iterators/flat_pairs.rs
index bb5bbb18..3af60124 100644
--- a/pest/src/iterators/flat_pairs.rs
+++ b/pest/src/iterators/flat_pairs.rs
@@ -7,8 +7,9 @@
 // option. All files in the project carrying such notice may not be copied,
 // modified, or distributed except according to those terms.
 
-use std::fmt;
-use std::rc::Rc;
+use alloc::rc::Rc;
+use alloc::vec::Vec;
+use core::fmt;
 
 use super::pair::{self, Pair};
 use super::queueable_token::QueueableToken;
@@ -151,6 +152,8 @@ impl<'i, R: Clone> Clone for FlatPairs<'i, R> {
 mod tests {
     use super::super::super::macros::tests::*;
     use super::super::super::Parser;
+    use alloc::vec;
+    use alloc::vec::Vec;
 
     #[test]
     fn iter_for_flat_pairs() {
diff --git a/pest/src/iterators/pair.rs b/pest/src/iterators/pair.rs
index 88844a35..de4e2da4 100644
--- a/pest/src/iterators/pair.rs
+++ b/pest/src/iterators/pair.rs
@@ -7,11 +7,13 @@
 // option. All files in the project carrying such notice may not be copied,
 // modified, or distributed except according to those terms.
 
-use std::fmt;
-use std::hash::{Hash, Hasher};
-use std::ptr;
-use std::rc::Rc;
-use std::str;
+use alloc::format;
+use alloc::rc::Rc;
+use alloc::vec::Vec;
+use core::fmt;
+use core::hash::{Hash, Hasher};
+use core::ptr;
+use core::str;
 
 #[cfg(feature = "pretty-print")]
 use serde::ser::SerializeStruct;
diff --git a/pest/src/iterators/pairs.rs b/pest/src/iterators/pairs.rs
index abae123e..8e164973 100644
--- a/pest/src/iterators/pairs.rs
+++ b/pest/src/iterators/pairs.rs
@@ -7,11 +7,14 @@
 // option. All files in the project carrying such notice may not be copied,
 // modified, or distributed except according to those terms.
 
-use std::fmt;
-use std::hash::{Hash, Hasher};
-use std::ptr;
-use std::rc::Rc;
-use std::str;
+use alloc::format;
+use alloc::rc::Rc;
+use alloc::string::String;
+use alloc::vec::Vec;
+use core::fmt;
+use core::hash::{Hash, Hasher};
+use core::ptr;
+use core::str;
 
 #[cfg(feature = "pretty-print")]
 use serde::ser::SerializeStruct;
@@ -302,6 +305,10 @@ impl<'i, R: RuleType> ::serde::Serialize for Pairs<'i, R> {
 mod tests {
     use super::super::super::macros::tests::*;
     use super::super::super::Parser;
+    use alloc::borrow::ToOwned;
+    use alloc::format;
+    use alloc::vec;
+    use alloc::vec::Vec;
 
     #[test]
     #[cfg(feature = "pretty-print")]
diff --git a/pest/src/iterators/tokens.rs b/pest/src/iterators/tokens.rs
index 59b75c52..2cb73e1f 100644
--- a/pest/src/iterators/tokens.rs
+++ b/pest/src/iterators/tokens.rs
@@ -7,9 +7,10 @@
 // option. All files in the project carrying such notice may not be copied,
 // modified, or distributed except according to those terms.
 
-use std::fmt;
-use std::rc::Rc;
-use std::str;
+use alloc::rc::Rc;
+use alloc::vec::Vec;
+use core::fmt;
+use core::str;
 
 use super::queueable_token::QueueableToken;
 use position;
@@ -132,6 +133,7 @@ mod tests {
     use super::super::super::macros::tests::*;
     use super::super::super::Parser;
     use super::Token;
+    use alloc::vec::Vec;
 
     #[test]
     fn double_ended_iter_for_tokens() {
diff --git a/pest/src/lib.rs b/pest/src/lib.rs
index 09e9d861..5cfcdd75 100644
--- a/pest/src/lib.rs
+++ b/pest/src/lib.rs
@@ -6,7 +6,7 @@
 // license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. All files in the project carrying such notice may not be copied,
 // modified, or distributed except according to those terms.
-
+#![no_std]
 #![cfg_attr(feature = "const_prec_climber", feature(const_fn))]
 
 //! # pest. The Elegant Parser
@@ -65,6 +65,9 @@
 
 #![doc(html_root_url = "https://docs.rs/pest")]
 
+extern crate alloc;
+#[cfg(feature = "std")]
+extern crate std;
 extern crate ucd_trie;
 
 #[cfg(feature = "pretty-print")]
@@ -72,12 +75,12 @@ extern crate serde;
 #[cfg(feature = "pretty-print")]
 extern crate serde_json;
 
+use core::fmt::Debug;
+use core::hash::Hash;
 pub use parser::Parser;
 pub use parser_state::{state, Atomicity, Lookahead, MatchDir, ParseResult, ParserState};
 pub use position::Position;
 pub use span::{Lines, Span};
-use std::fmt::Debug;
-use std::hash::Hash;
 pub use token::Token;
 
 pub mod error;
diff --git a/pest/src/macros.rs b/pest/src/macros.rs
index 6c7e6171..f81d234c 100644
--- a/pest/src/macros.rs
+++ b/pest/src/macros.rs
@@ -318,6 +318,9 @@ pub mod tests {
     use super::super::error::Error;
     use super::super::iterators::Pairs;
     use super::super::{state, Parser};
+    use alloc::format;
+    use alloc::vec;
+    use alloc::vec::Vec;
 
     #[allow(non_camel_case_types)]
     #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
diff --git a/pest/src/parser_state.rs b/pest/src/parser_state.rs
index 09bc9271..ead92cac 100644
--- a/pest/src/parser_state.rs
+++ b/pest/src/parser_state.rs
@@ -7,8 +7,11 @@
 // option. All files in the project carrying such notice may not be copied,
 // modified, or distributed except according to those terms.
 
-use std::ops::Range;
-use std::rc::Rc;
+use alloc::boxed::Box;
+use alloc::rc::Rc;
+use alloc::vec;
+use alloc::vec::Vec;
+use core::ops::Range;
 
 use error::{Error, ErrorVariant};
 use iterators::{pairs, QueueableToken};
diff --git a/pest/src/position.rs b/pest/src/position.rs
index 0591b3e2..04e392a8 100644
--- a/pest/src/position.rs
+++ b/pest/src/position.rs
@@ -7,12 +7,12 @@
 // option. All files in the project carrying such notice may not be copied,
 // modified, or distributed except according to those terms.
 
-use std::cmp::Ordering;
-use std::fmt;
-use std::hash::{Hash, Hasher};
-use std::ops::Range;
-use std::ptr;
-use std::str;
+use core::cmp::Ordering;
+use core::fmt;
+use core::hash::{Hash, Hasher};
+use core::ops::Range;
+use core::ptr;
+use core::str;
 
 use span;
 
@@ -427,8 +427,6 @@ impl<'i> Hash for Position<'i> {
 
 #[cfg(test)]
 mod tests {
-    use std::collections::HashSet;
-
     use super::*;
 
     #[test]
@@ -609,7 +607,10 @@ mod tests {
     }
 
     #[test]
+    #[cfg(feature = "std")]
     fn hash() {
+        use std::collections::HashSet;
+
         let input = "a";
         let start = Position::from_start(input);
         let mut positions = HashSet::new();
diff --git a/pest/src/prec_climber.rs b/pest/src/prec_climber.rs
index 5d4057b0..e6237a95 100644
--- a/pest/src/prec_climber.rs
+++ b/pest/src/prec_climber.rs
@@ -9,9 +9,11 @@
 
 //! Constructs useful in infix operator parsing with the precedence climbing method.
 
-use std::borrow::Cow;
-use std::iter::Peekable;
-use std::ops::BitOr;
+use alloc::borrow::Cow;
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use core::iter::Peekable;
+use core::ops::BitOr;
 
 use iterators::Pair;
 use RuleType;
diff --git a/pest/src/span.rs b/pest/src/span.rs
index f8beffe2..0c58c589 100644
--- a/pest/src/span.rs
+++ b/pest/src/span.rs
@@ -7,10 +7,10 @@
 // option. All files in the project carrying such notice may not be copied,
 // modified, or distributed except according to those terms.
 
-use std::fmt;
-use std::hash::{Hash, Hasher};
-use std::ptr;
-use std::str;
+use core::fmt;
+use core::hash::{Hash, Hasher};
+use core::ptr;
+use core::str;
 
 use position;
 
@@ -262,6 +262,8 @@ impl<'i> Iterator for Lines<'i> {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use alloc::borrow::ToOwned;
+    use alloc::vec::Vec;
 
     #[test]
     fn split() {
@@ -281,7 +283,7 @@ mod tests {
         let input = "abc\ndef\nghi";
         let span = Span::new(input, 1, 7).unwrap();
         let lines: Vec<_> = span.lines().collect();
-        println!("{:?}", lines);
+        //println!("{:?}", lines);
         assert_eq!(lines.len(), 2);
         assert_eq!(lines[0], "abc\n".to_owned());
         assert_eq!(lines[1], "def\n".to_owned());
@@ -293,7 +295,7 @@ mod tests {
         let span = Span::new(input, 5, 11).unwrap();
         assert!(span.end_pos().at_end());
         let lines: Vec<_> = span.lines().collect();
-        println!("{:?}", lines);
+        //println!("{:?}", lines);
         assert_eq!(lines.len(), 2);
         assert_eq!(lines[0], "def\n".to_owned());
         assert_eq!(lines[1], "ghi".to_owned());
diff --git a/pest/src/stack.rs b/pest/src/stack.rs
index dede80f1..05ac11f6 100644
--- a/pest/src/stack.rs
+++ b/pest/src/stack.rs
@@ -7,7 +7,9 @@
 // option. All files in the project carrying such notice may not be copied,
 // modified, or distributed except according to those terms.
 
-use std::ops::{Index, Range};
+use alloc::vec;
+use alloc::vec::Vec;
+use core::ops::{Index, Range};
 
 /// Implementation of a `Stack` which maintains an log of `StackOp`s in order to rewind the stack
 /// to a previous state.
diff --git a/pest/src/unicode/mod.rs b/pest/src/unicode/mod.rs
index 3def67e3..912a7ece 100644
--- a/pest/src/unicode/mod.rs
+++ b/pest/src/unicode/mod.rs
@@ -5,6 +5,8 @@
 #![allow(bad_style)]
 #![allow(clippy::all)]
 
+use alloc::boxed::Box;
+
 macro_rules! char_property_functions {
     {$(
         mod $module:ident;


Test patch: