#[derive(Clone, Debug, PartialEq, Eq)] pub enum Token<'a> { Keyword(Keyword), Ident(&'a str), Punct(Punct), Str(Str<'a>), Number(&'a str), } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Keyword { Else, False, Fetch, Fn, For, If, Let, Map, Mut, None, Recipe, Set, Task, True, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Punct(pub char, pub Spacing); #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Spacing { Alone, Joint, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct Str<'a> { pub pieces: Vec>, pub kind: StrKind, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum StrPiece<'a> { Chars(&'a str), Escape(char), Interp(TokenStream<'a>), } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum StrKind { Regular, Raw, Script, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct TokenStream<'a>(pub Vec>); impl<'a> peg::Parse for TokenStream<'a> { 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) -> Self::PositionRepr { pos } } impl<'input, 'a: 'input> peg::ParseElem<'input> for TokenStream<'a> { type Element = &'input Token<'a>; fn parse_elem(&'input self, pos: usize) -> peg::RuleResult { use peg::RuleResult; match self.0[pos..].first() { Some(c) => RuleResult::Matched(pos + 1, c), None => RuleResult::Failed, } } }