ionpak-thermostat/firmware/src/command_parser.rs

126 lines
3.1 KiB
Rust
Raw Normal View History

use logos::Logos;
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,
#[token = "pwm"]
Pwm,
2019-09-11 05:37:51 +08:00
#[regex = "[0-9]+"]
Number,
}
#[derive(Debug)]
pub enum Error {
Parser,
UnexpectedEnd,
UnexpectedToken(Token),
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)]
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,
Show(ShowCommand),
2019-09-11 05:37:51 +08:00
Report(ReportMode),
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
}
)*
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),
_ => 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)),
],
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
]
}
}