use peg::{Parse, ParseElem, RuleResult};
pub struct SliceByRef<'a, T>(pub &'a [T]);
impl<'a, T> Parse for SliceByRef<'a, T> {
type PositionRepr = usize;
fn start(&self) -> usize {
0
}
fn is_eof(&self, pos: usize) -> bool {
pos >= self.0.len()
}
fn position_repr(&self, pos: usize) -> usize {
pos
}
}
impl<'a, T: 'a> ParseElem<'a> for SliceByRef<'a, T> {
type Element = &'a T;
fn parse_elem(&'a self, pos: usize) -> RuleResult<&'a T> {
match self.0[pos..].first() {
Some(c) => RuleResult::Matched(pos + 1, c),
None => RuleResult::Failed,
}
}
}
#[derive(PartialEq)]
pub enum TokenType {
Word,
Number,
}
pub struct Token {
pub token_type: TokenType,
}
peg::parser! {
grammar tokenparser<'a>() for SliceByRef<'a, Token> {
pub rule word_by_field() = [ Token { token_type: TokenType::Word, .. } ]
pub rule word_by_eq() = [t if t.token_type == TokenType::Word]
rule tok(ty: TokenType) -> &'input Token = [t if t.token_type == ty]
pub rule number() = tok(TokenType::Number)
}
}
#[test]
fn main() {
let word_tok = [Token {
token_type: TokenType::Word,
}];
let number_tok = [Token {
token_type: TokenType::Number,
}];
assert!(tokenparser::word_by_field(&SliceByRef(&word_tok[..])).is_ok());
assert!(tokenparser::word_by_eq(&SliceByRef(&word_tok[..])).is_ok());
assert!(tokenparser::number(&SliceByRef(&number_tok[..])).is_ok());
}