mx-sanebot: port the parsing over to a more formal implementation
This commit is contained in:
parent
b0c68308b7
commit
7c1961eba8
|
@ -3,7 +3,7 @@ use std::fmt;
|
|||
use std::process;
|
||||
use std::str;
|
||||
|
||||
use super::parsing;
|
||||
use super::parsing::{self, Parser};
|
||||
|
||||
|
||||
mod tt {
|
||||
|
@ -12,6 +12,7 @@ mod tt {
|
|||
Lit,
|
||||
Then,
|
||||
};
|
||||
use crate::ilit;
|
||||
|
||||
// grammar:
|
||||
// REQUEST = <!> (HELP | BT | BT-ADD)
|
||||
|
@ -26,15 +27,15 @@ mod tt {
|
|||
pub(super) type Bang = Lit<{ '!' as u8 }>;
|
||||
|
||||
pub(super) type Help = Then<
|
||||
Lit<{ 'H' as u8 }>, Then<
|
||||
Lit<{ 'E' as u8 }>, Then<
|
||||
Lit<{ 'L' as u8 }>,
|
||||
Lit<{ 'P' as u8 }>,
|
||||
ilit!('H'), Then<
|
||||
ilit!('E'), Then<
|
||||
ilit!('L'),
|
||||
ilit!('P'),
|
||||
>>>;
|
||||
|
||||
pub(super) type Bt = Then<
|
||||
Lit<{ 'B' as u8 }>,
|
||||
Lit<{ 'T' as u8 }>,
|
||||
ilit!('B'),
|
||||
ilit!('T'),
|
||||
>;
|
||||
}
|
||||
|
||||
|
@ -51,11 +52,9 @@ impl MessageHandler {
|
|||
}
|
||||
|
||||
fn parse_msg(&self, msg: &str) -> Result<Request, ()> {
|
||||
let msg = msg.trim();
|
||||
match msg {
|
||||
"!help" => Ok(Request::Help),
|
||||
"!bt" => Ok(Request::Bt),
|
||||
_ => Err(())
|
||||
match msg.as_bytes().parse_all::<tt::Request>() {
|
||||
Ok(req) => Ok(req.into()),
|
||||
Err(_) => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,12 @@ pub enum Either<A, B> {
|
|||
}
|
||||
|
||||
// case-insensitive u8 character.
|
||||
// type ILit<const BYTE: u8> = Either<Lit<{ BYTE.to_ascii_lowercase() }>, Lit<{ BYTE.to_ascii_uppercase() }>>;
|
||||
#[macro_export]
|
||||
macro_rules! ilit {
|
||||
($BYTE:literal) => {
|
||||
Either<Lit<{ ($BYTE as u8).to_ascii_lowercase() }>, Lit<{ ($BYTE as u8).to_ascii_uppercase() }>>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub type PResult<P, C> = std::result::Result<(C, P), P>;
|
||||
|
@ -37,6 +42,25 @@ pub trait Parser: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Parser for &'a [u8] {
|
||||
fn expect_byte(self, b: Option<u8>) -> PResult<Self, ()> {
|
||||
match (b, self.split_first()) {
|
||||
// expected the correct character
|
||||
(Some(exp), Some((first, rest))) if *first == exp => Ok( ((), rest) ),
|
||||
// expected EOF, got EOF
|
||||
(None, None) => Ok( ((), self)),
|
||||
_ => Err(self),
|
||||
}
|
||||
}
|
||||
fn expect<C: Parse>(self) -> PResult<Self, C> {
|
||||
match C::consume(self.clone()) {
|
||||
Ok(res) => Ok(res),
|
||||
// rewind the parser should we fail
|
||||
Err(_p) => Err(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Parse: Sized {
|
||||
fn consume<P: Parser>(p: P) -> PResult<P, Self>;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user