Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make pest_generator / pest_derive no_std compatible. #513

Merged
merged 6 commits into from
Oct 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ readme = "_README.md"
name = "pest_derive"
proc-macro = true

[features]
default = ["std"]
std = ["pest/std", "pest_generator/std"]

[dependencies]
# for tests, included transitively anyway
pest = { path = "../pest", version = "2.1.0" }
pest_generator = { path = "../generator", version = "2.1.0" }
pest = { path = "../pest", version = "2.1.0", default-features = false }
pest_generator = { path = "../generator", version = "2.1.0", default-features = false }

[badges]
codecov = { repository = "pest-parser/pest" }
Expand Down
3 changes: 3 additions & 0 deletions derive/tests/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.
#![allow(unknown_lints, clippy)]
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use alloc::{format, vec::Vec};

#[macro_use]
extern crate pest;
Expand Down
4 changes: 4 additions & 0 deletions derive/tests/grammar_inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use alloc::{format, vec::Vec};

#[macro_use]
extern crate pest;
#[macro_use]
Expand Down
4 changes: 4 additions & 0 deletions derive/tests/lists.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use alloc::{format, vec::Vec};

#[macro_use]
extern crate pest;
#[macro_use]
Expand Down
4 changes: 4 additions & 0 deletions derive/tests/reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use alloc::vec;

#[macro_use]
extern crate pest;
#[macro_use]
Expand Down
8 changes: 6 additions & 2 deletions generator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "pest_generator"
description = "pest code generator"
version = "2.1.3"
version = "2.1.4"
authors = ["Dragoș Tiselice <dragostiselice@gmail.com>"]
homepage = "https://pest-parser.github.io/"
repository = "https://github.com/pest-parser/pest"
Expand All @@ -11,8 +11,12 @@ categories = ["parsing"]
license = "MIT/Apache-2.0"
readme = "_README.md"

[features]
default = ["std"]
std = ["pest/std"]

[dependencies]
pest = { path = "../pest", version = "2.1.0" }
pest = { path = "../pest", version = "2.1.0", default-features = false }
pest_meta = { path = "../meta", version = "2.1.0" }
proc-macro2 = "1.0"
quote = "1.0"
Expand Down
59 changes: 46 additions & 13 deletions generator/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,15 @@ pub fn generate(

let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

let result = result_type();

let parser_impl = quote! {
#[allow(clippy::all)]
impl #impl_generics ::pest::Parser<Rule> for #name #ty_generics #where_clause {
fn parse<'i>(
rule: Rule,
input: &'i str
) -> ::std::result::Result<
) -> #result<
::pest::iterators::Pairs<'i, Rule>,
::pest::error::Error<Rule>
> {
Expand Down Expand Up @@ -148,13 +150,15 @@ fn generate_builtin_rules() -> Vec<(&'static str, TokenStream)> {
.or_else(|state| state.match_string("\r"))
);

let box_ty = box_type();

for property in UNICODE_PROPERTY_NAMES {
let property_ident: Ident = syn::parse_str(property).unwrap();
// insert manually for #property substitution
builtins.push((property, quote! {
#[inline]
#[allow(dead_code, non_snake_case, unused_variables)]
fn #property_ident(state: Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
fn #property_ident(state: #box_ty<::pest::ParserState<Rule>>) -> ::pest::ParseResult<#box_ty<::pest::ParserState<Rule>>> {
state.match_char_by(::pest::unicode::#property_ident)
}
}));
Expand Down Expand Up @@ -233,11 +237,13 @@ fn generate_rule(rule: OptimizedRule) -> TokenStream {
generate_expr(rule.expr)
};

let box_ty = box_type();

match rule.ty {
RuleType::Normal => quote! {
#[inline]
#[allow(non_snake_case, unused_variables)]
pub fn #name(state: Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
pub fn #name(state: #box_ty<::pest::ParserState<Rule>>) -> ::pest::ParseResult<#box_ty<::pest::ParserState<Rule>>> {
state.rule(Rule::#name, |state| {
#expr
})
Expand All @@ -246,14 +252,14 @@ fn generate_rule(rule: OptimizedRule) -> TokenStream {
RuleType::Silent => quote! {
#[inline]
#[allow(non_snake_case, unused_variables)]
pub fn #name(state: Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
pub fn #name(state: #box_ty<::pest::ParserState<Rule>>) -> ::pest::ParseResult<#box_ty<::pest::ParserState<Rule>>> {
#expr
}
},
RuleType::Atomic => quote! {
#[inline]
#[allow(non_snake_case, unused_variables)]
pub fn #name(state: Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
pub fn #name(state: #box_ty<::pest::ParserState<Rule>>) -> ::pest::ParseResult<#box_ty<::pest::ParserState<Rule>>> {
state.rule(Rule::#name, |state| {
state.atomic(::pest::Atomicity::Atomic, |state| {
#expr
Expand All @@ -264,7 +270,7 @@ fn generate_rule(rule: OptimizedRule) -> TokenStream {
RuleType::CompoundAtomic => quote! {
#[inline]
#[allow(non_snake_case, unused_variables)]
pub fn #name(state: Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
pub fn #name(state: #box_ty<::pest::ParserState<Rule>>) -> ::pest::ParseResult<#box_ty<::pest::ParserState<Rule>>> {
state.atomic(::pest::Atomicity::CompoundAtomic, |state| {
state.rule(Rule::#name, |state| {
#expr
Expand All @@ -275,7 +281,7 @@ fn generate_rule(rule: OptimizedRule) -> TokenStream {
RuleType::NonAtomic => quote! {
#[inline]
#[allow(non_snake_case, unused_variables)]
pub fn #name(state: Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
pub fn #name(state: #box_ty<::pest::ParserState<Rule>>) -> ::pest::ParseResult<#box_ty<::pest::ParserState<Rule>>> {
state.atomic(::pest::Atomicity::NonAtomic, |state| {
state.rule(Rule::#name, |state| {
#expr
Expand Down Expand Up @@ -613,13 +619,38 @@ struct QuoteOption<T>(Option<T>);

impl<T: ToTokens> ToTokens for QuoteOption<T> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let option = option_type();
tokens.append_all(match self.0 {
Some(ref t) => quote! { ::std::option::Option::Some(#t) },
None => quote! { ::std::option::Option::None },
Some(ref t) => quote! { #option::Some(#t) },
None => quote! { #option::None },
});
}
}

fn box_type() -> TokenStream {
#[cfg(feature = "std")]
quote! { ::std::boxed::Box }

#[cfg(not(feature = "std"))]
quote! { ::alloc::boxed::Box }
}

fn result_type() -> TokenStream {
#[cfg(feature = "std")]
quote! { ::std::result::Result }

#[cfg(not(feature = "std"))]
quote! { ::core::result::Result }
}

fn option_type() -> TokenStream {
#[cfg(feature = "std")]
quote! { ::std::option::Option }

#[cfg(not(feature = "std"))]
quote! { ::core::option::Option }
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -929,6 +960,8 @@ mod tests {
expr: OptimizedExpr::Str("b".to_owned()),
}];
let defaults = vec!["ANY"];
let result = result_type();
let box_ty = box_type();
assert_eq!(
generate(name, &generics, Some(String::from("test.pest")), rules, defaults, true).to_string(),
quote! {
Expand All @@ -946,7 +979,7 @@ mod tests {
fn parse<'i>(
rule: Rule,
input: &'i str
) -> ::std::result::Result<
) -> #result<
::pest::iterators::Pairs<'i, Rule>,
::pest::error::Error<Rule>
> {
Expand All @@ -957,7 +990,7 @@ mod tests {

#[inline]
#[allow(dead_code, non_snake_case, unused_variables)]
pub fn skip(state: Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
pub fn skip(state: #box_ty<::pest::ParserState<Rule>>) -> ::pest::ParseResult<#box_ty<::pest::ParserState<Rule>>> {
Ok(state)
}
}
Expand All @@ -967,13 +1000,13 @@ mod tests {

#[inline]
#[allow(non_snake_case, unused_variables)]
pub fn a(state: Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
pub fn a(state: #box_ty<::pest::ParserState<Rule>>) -> ::pest::ParseResult<#box_ty<::pest::ParserState<Rule>>> {
state.match_string("b")
}

#[inline]
#[allow(dead_code, non_snake_case, unused_variables)]
pub fn ANY(state: Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
pub fn ANY(state: #box_ty<::pest::ParserState<Rule>>) -> ::pest::ParseResult<#box_ty<::pest::ParserState<Rule>>> {
state.skip(1)
}
}
Expand Down
32 changes: 30 additions & 2 deletions generator/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,52 @@ macro_rules! insert_public_builtin {
};
}

#[cfg(feature = "std")]
macro_rules! generate_rule {
($name: ident, $pattern: expr) => {
quote! {
#[inline]
#[allow(dead_code, non_snake_case, unused_variables)]
pub fn $name(state: Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
pub fn $name(state: ::std::boxed::Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<Rule>>> {
$pattern
}
}
}
}

#[cfg(not(feature = "std"))]
macro_rules! generate_rule {
($name: ident, $pattern: expr) => {
quote! {
#[inline]
#[allow(dead_code, non_snake_case, unused_variables)]
pub fn $name(state: ::alloc::boxed::Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<::alloc::boxed::Box<::pest::ParserState<Rule>>> {
$pattern
}
}
}
}

#[cfg(feature = "std")]
macro_rules! generate_public_rule {
($name: ident, $pattern: expr) => {
quote! {
#[inline]
#[allow(dead_code, non_snake_case, unused_variables)]
pub fn $name(state: ::std::boxed::Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<Rule>>> {
$pattern
}
}
}
}

#[cfg(not(feature = "std"))]
macro_rules! generate_public_rule {
($name: ident, $pattern: expr) => {
quote! {
#[inline]
#[allow(dead_code, non_snake_case, unused_variables)]
pub fn $name(state: Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
pub fn $name(state: ::alloc::boxed::Box<::pest::ParserState<Rule>>) -> ::pest::ParseResult<::alloc::boxed::Box<::pest::ParserState<Rule>>> {
$pattern
}
}
Expand Down