2019-09-11 06:23:15 +08:00
|
|
|
use logos::Logos;
|
2019-09-14 09:09:07 +08:00
|
|
|
use btoi::{btoi, ParseIntegerError};
|
2019-09-11 05:37:51 +08:00
|
|
|
use super::session::ReportMode;
|
|
|
|
|
|
|
|
#[derive(Logos, Debug, PartialEq)]
|
|
|
|
enum Token {
|
|
|
|
#[end]
|
|
|
|
End,
|
|
|
|
#[error]
|
|
|
|
Error,
|
|
|
|
|
|
|
|
#[token = "Quit"]
|
|
|
|
Quit,
|
|
|
|
#[token = "report"]
|
|
|
|
Report,
|
|
|
|
#[token = "mode"]
|
|
|
|
Mode,
|
|
|
|
#[token = "off"]
|
|
|
|
Off,
|
|
|
|
#[token = "once"]
|
|
|
|
Once,
|
|
|
|
#[token = "continuous"]
|
|
|
|
Continuous,
|
2019-09-14 09:09:07 +08:00
|
|
|
#[token = "pwm"]
|
|
|
|
Pwm,
|
2019-09-11 05:37:51 +08:00
|
|
|
|
|
|
|
#[regex = "[0-9]+"]
|
|
|
|
Number,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Error {
|
|
|
|
Parser,
|
|
|
|
UnexpectedEnd,
|
|
|
|
UnexpectedToken(Token),
|
2019-09-14 09:09:07 +08:00
|
|
|
ParseInteger(ParseIntegerError)
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ParseIntegerError> for Error {
|
|
|
|
fn from(e: ParseIntegerError) -> Self {
|
|
|
|
Error::ParseInteger(e)
|
|
|
|
}
|
2019-09-11 05:37:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2019-09-11 06:23:15 +08:00
|
|
|
pub enum ShowCommand {
|
2019-09-11 05:37:51 +08:00
|
|
|
ReportMode,
|
2019-09-12 22:12:03 +08:00
|
|
|
}
|
|
|
|
|
2019-09-11 05:37:51 +08:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Command {
|
|
|
|
Quit,
|
2019-09-11 06:23:15 +08:00
|
|
|
Show(ShowCommand),
|
2019-09-11 05:37:51 +08:00
|
|
|
Report(ReportMode),
|
2019-09-14 09:09:07 +08:00
|
|
|
Pwm {
|
|
|
|
pwm_match: u32,
|
|
|
|
pwm_reload: u32,
|
|
|
|
},
|
2019-09-11 05:37:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Command {
|
|
|
|
pub fn parse(input: &str) -> Result<Self, Error> {
|
|
|
|
let mut lexer = Token::lexer(input);
|
|
|
|
|
2019-09-13 07:04:59 +08:00
|
|
|
/// Match against a set of expected tokens
|
2019-09-11 05:37:51 +08:00
|
|
|
macro_rules! choice {
|
|
|
|
[$($token: tt => $block: stmt,)*] => {
|
|
|
|
match lexer.token {
|
|
|
|
$(
|
|
|
|
Token::$token => {
|
|
|
|
lexer.advance();
|
|
|
|
$block
|
|
|
|
}
|
|
|
|
)*
|
2019-09-13 07:10:31 +08:00
|
|
|
Token::End => return Err(Error::UnexpectedEnd),
|
|
|
|
_ => return Err(Error::UnexpectedToken(lexer.token))
|
2019-09-11 05:37:51 +08:00
|
|
|
}
|
2019-09-13 07:04:59 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
/// Expecting no further tokens
|
|
|
|
macro_rules! end {
|
|
|
|
($result: expr) => {
|
|
|
|
match lexer.token {
|
|
|
|
Token::End => Ok($result),
|
2019-09-13 07:10:31 +08:00
|
|
|
_ => return Err(Error::UnexpectedToken(lexer.token)),
|
2019-09-13 07:04:59 +08:00
|
|
|
}
|
|
|
|
};
|
2019-09-11 05:37:51 +08:00
|
|
|
}
|
|
|
|
|
2019-09-13 07:04:59 +08:00
|
|
|
// Command grammar
|
2019-09-11 05:37:51 +08:00
|
|
|
choice![
|
|
|
|
Quit => Ok(Command::Quit),
|
|
|
|
Report => choice![
|
|
|
|
Mode => choice![
|
2019-09-13 07:04:59 +08:00
|
|
|
End => end!(Command::Show(ShowCommand::ReportMode)),
|
2019-09-11 05:37:51 +08:00
|
|
|
Off => Ok(Command::Report(ReportMode::Off)),
|
|
|
|
Once => Ok(Command::Report(ReportMode::Once)),
|
|
|
|
Continuous => Ok(Command::Report(ReportMode::Continuous)),
|
|
|
|
],
|
|
|
|
End => Ok(Command::Report(ReportMode::Once)),
|
|
|
|
],
|
2019-09-14 09:09:07 +08:00
|
|
|
Pwm => {
|
|
|
|
if lexer.token != Token::Number {
|
|
|
|
return Err(Error::UnexpectedToken(lexer.token));
|
|
|
|
}
|
|
|
|
let pwm_match = btoi(lexer.slice().as_bytes())?;
|
|
|
|
lexer.advance();
|
|
|
|
|
|
|
|
if lexer.token != Token::Number {
|
|
|
|
return Err(Error::UnexpectedToken(lexer.token));
|
|
|
|
}
|
|
|
|
let pwm_reload = btoi(lexer.slice().as_bytes())?;
|
|
|
|
lexer.advance();
|
|
|
|
|
|
|
|
if lexer.token != Token::End {
|
|
|
|
return Err(Error::UnexpectedToken(lexer.token));
|
|
|
|
}
|
|
|
|
|
|
|
|
end!(Command::Pwm {
|
|
|
|
pwm_match, pwm_reload,
|
|
|
|
})
|
|
|
|
},
|
2019-09-11 05:37:51 +08:00
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|