at_commands/parser/
response_parser.rsuse {
crate::lowlevel::{HardcodedError, Response},
crate::parser::{
arguments_parser::ArgumentsParser,
common::{
next_match, next_match_one_of, parse_integer, parse_name, parse_string, ParseError,
ParseResult,
},
response_grammar::{Grammar, Rule},
},
pest::{iterators::Pair, Parser},
};
static ARGUMENTS_PARSER: ArgumentsParser<Rule> = ArgumentsParser {
argument_list: Rule::argument_list,
argument: Rule::argument,
arguments: Rule::arguments,
key_value_argument: Rule::key_value_argument,
optional_argument_delimiter: Rule::optional_argument_delimiter,
optional_argument_terminator: Rule::optional_argument_terminator,
parenthesized_argument_lists: Rule::parenthesized_argument_lists,
primitive_argument: Rule::primitive_argument,
};
pub fn parse(string: &String) -> ParseResult<Response, Rule> {
let mut parsed = Grammar::parse(Rule::input, string).map_err(|pest_error| {
ParseError::PestParseFailure { string: string.clone(), pest_error }
})?;
let input = next_match(&mut parsed, Rule::input)?;
let mut input_elements = input.into_inner();
let response = next_match(&mut input_elements, Rule::response)?;
parse_response(response)
}
fn parse_response(response: Pair<'_, Rule>) -> ParseResult<Response, Rule> {
let mut response_elements = response.into_inner();
let response_variant = next_match_one_of(
&mut response_elements,
vec![Rule::ok, Rule::error, Rule::hardcoded_error, Rule::cme_error, Rule::success],
)?;
let parsed_response = match response_variant.as_rule() {
Rule::ok => Response::Ok,
Rule::error => Response::Error,
Rule::hardcoded_error => parse_hardcoded_error(response_variant)?,
Rule::cme_error => parse_cme_error(response_variant)?,
Rule::success => parse_success(response_variant)?,
_ => unreachable!(),
};
Ok(parsed_response)
}
fn parse_hardcoded_error(hardcoded_error: Pair<'_, Rule>) -> ParseResult<Response, Rule> {
let error_string = parse_string(hardcoded_error)?;
let parsed_error = match error_string.as_str() {
"NO CARRIER" => HardcodedError::NoCarrier,
"BUSY" => HardcodedError::Busy,
"NO ANSWER" => HardcodedError::NoAnswer,
"DELAYED" => HardcodedError::Delayed,
"BLACKLIST" => HardcodedError::Blacklist,
_ => unreachable!(),
};
Ok(Response::HardcodedError(parsed_error))
}
fn parse_cme_error(cme_error: Pair<'_, Rule>) -> ParseResult<Response, Rule> {
let mut cme_error_elements = cme_error.into_inner();
let error_code = next_match(&mut cme_error_elements, Rule::integer)?;
let parsed_error_code = parse_integer(error_code)?;
Ok(Response::CmeError(parsed_error_code))
}
fn parse_success(success: Pair<'_, Rule>) -> ParseResult<Response, Rule> {
let mut success_elements = success.into_inner();
let optional_extension = next_match(&mut success_elements, Rule::optional_extension)?;
let parsed_optional_extension = parse_optional_extension(optional_extension)?;
let name = next_match(&mut success_elements, Rule::command_name)?;
let parsed_name = parse_name(name)?;
let delimited_arguments = next_match(&mut success_elements, Rule::delimited_arguments)?;
let parsed_delimited_arguments =
ARGUMENTS_PARSER.parse_delimited_arguments(delimited_arguments)?;
Ok(Response::Success {
name: parsed_name,
is_extension: parsed_optional_extension,
arguments: parsed_delimited_arguments,
})
}
fn parse_optional_extension(optional_extension: Pair<'_, Rule>) -> ParseResult<bool, Rule> {
let extension_str = optional_extension.as_span().as_str();
match extension_str {
"" => Ok(false),
"+" => Ok(true),
c => Err(ParseError::UnknownExtensionCharacter(c.to_string())),
}
}