Skip to content

want to specify lifetime bound between 'input and custom input lifetime 'a #291

Open
@kingrongH

Description

@kingrongH

Background

I have wrapped str with StrInput and StrInputSlice myself, and have impl ParseSlice for StrInput, and then I can use $() symbol to get StrInputSlice in which way I can get whole input str access. This is very nice, this is also the reason I chose rust-peg over pest.

pub struct StrInput <'a> {
    pub input: &'a str,
}

pub struct StrInputSlice<'a> {
    pub input: &'a str,
    pub start: usize,
    pub end: usize
}

impl<'a> StrInput<'a> {

    pub fn new(input: &'a str) -> Self {
        Self {input}
    }

    pub fn slice(&self, start: usize, end: usize) -> StrInputSlice {
        StrInputSlice {
            input: self.input,
            start, end
        }
    }
    
}

impl<'a> StrInputSlice<'a> {

    pub fn get_slice(&self) -> &'a str {
        &self.input[self.start..self.end]
    }

}

impl<'a> peg::ParseSlice<'a> for StrInput<'a> {

    type Slice = StrInputSlice<'a>;

    fn parse_slice(&'a self, p1: usize, p2: usize) -> Self::Slice {
        self.slice(p1, p2)
    }
}

Problem is here

but for zero-copy reason, I also want to return sliced str from StrInput<'a> , but I got a life time error for the code below. cuz StringInputSlice is parsed by ParseSlice::parse_slice with a impilict 'input life time so that we can't return StrInputSlice with 'a lifetime

parser!(grammar test_parser<'a>() for StrInput<'a> {

    /// the reason I wrap str with `StrInput` and `StrInputSlice` is here. I want a way that I can access previous chars(look behind?). 
    rule check_previous() = slice: $(['*']+)  {?
        if slice.start == 0 {
            return Ok(());
        }
        // unwrap here is ok
        let char_before = &slice.input[slice.start..slice.end].chars().rev().next().unwrap();
        if *char_before != ' ' {
            return Err("should preceded by space")
        }
        Ok(())
    }

    // here we got an error, 
    // cuz StringInputSlice is parsed by `ParseSlice::parse_slice` with a impilict `'input` life time 
    // so that we can't return StrInputSlice with `'a` lifetime
    rule parse_slice() -> StrInputSlice<'a> = slice:$([_]*) {
        slice
    }

});

Thoughts

  1. maybe rust-peg can add a way we can use 'input lifetime.
parser!(grammar test_parser() for StrInput<'input> {
// ...
});
  1. add a way we can add a lifetime bound 'input: 'a
parser!(grammar test_parser2<'a>() for StrInput<'a>
where 'input: 'a
{
    // ...
});

or maybe both 😀

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions