at_commands/parser/
command_parser.rs
1use {
11 crate::{
12 lowlevel::Command,
13 parser::{
14 arguments_parser::ArgumentsParser,
15 command_grammar::{Grammar, Rule},
16 common::{next_match, next_match_one_of, parse_name, ParseError, ParseResult},
17 },
18 },
19 pest::{iterators::Pair, Parser},
20};
21
22static ARGUMENTS_PARSER: ArgumentsParser<Rule> = ArgumentsParser {
23 argument_list: Rule::argument_list,
24 argument: Rule::argument,
25 arguments: Rule::arguments,
26 key_value_argument: Rule::key_value_argument,
27 optional_argument_delimiter: Rule::optional_argument_delimiter,
28 optional_argument_terminator: Rule::optional_argument_terminator,
29 parenthesized_argument_lists: Rule::parenthesized_argument_lists,
30 primitive_argument: Rule::primitive_argument,
31};
32
33pub fn parse(string: &str) -> ParseResult<Command, Rule> {
34 let mut parsed = Grammar::parse(Rule::input, string)
35 .map_err(|pest_error| ParseError::PestParseFailure { string: string.into(), pest_error })?;
36
37 let input = next_match(&mut parsed, Rule::input)?;
38 let mut input_elements = input.into_inner();
39 let command = next_match(&mut input_elements, Rule::command)?;
40
41 parse_command(command)
42}
43
44fn parse_command(command: Pair<'_, Rule>) -> ParseResult<Command, Rule> {
45 let mut command_elements = command.into_inner();
46 let command_variant =
47 next_match_one_of(&mut command_elements, vec![Rule::execute, Rule::read, Rule::test])?;
48
49 let parsed_command = match command_variant.as_rule() {
50 Rule::execute => parse_execute(command_variant),
51 Rule::read => parse_read(command_variant),
52 Rule::test => parse_test(command_variant),
53 _ => unreachable!(),
57 }?;
58
59 Ok(parsed_command)
60}
61
62fn parse_execute(execute: Pair<'_, Rule>) -> ParseResult<Command, Rule> {
63 let mut execute_elements = execute.into_inner();
64
65 let optional_extension = next_match(&mut execute_elements, Rule::optional_extension)?;
66 let parsed_optional_extension = parse_optional_extension(optional_extension)?;
67
68 let name = next_match(&mut execute_elements, Rule::command_name)?;
69 let parsed_name = parse_name(name)?;
70
71 let delimited_arguments = next_match(&mut execute_elements, Rule::delimited_arguments)?;
72 let parsed_delimited_arguments =
73 ARGUMENTS_PARSER.parse_delimited_arguments(delimited_arguments)?;
74
75 Ok(Command::Execute {
76 name: parsed_name,
77 is_extension: parsed_optional_extension,
78 arguments: parsed_delimited_arguments,
79 })
80}
81
82fn parse_read(read: Pair<'_, Rule>) -> ParseResult<Command, Rule> {
83 let mut read_elements = read.into_inner();
84
85 let optional_extension = next_match(&mut read_elements, Rule::optional_extension)?;
86 let parsed_optional_extension = parse_optional_extension(optional_extension)?;
87
88 let name = next_match(&mut read_elements, Rule::command_name)?;
89 let parsed_name = parse_name(name)?;
90
91 Ok(Command::Read { name: parsed_name, is_extension: parsed_optional_extension })
92}
93
94fn parse_test(test: Pair<'_, Rule>) -> ParseResult<Command, Rule> {
95 let mut test_elements = test.into_inner();
96
97 let optional_extension = next_match(&mut test_elements, Rule::optional_extension)?;
98 let parsed_optional_extension = parse_optional_extension(optional_extension)?;
99
100 let name = next_match(&mut test_elements, Rule::command_name)?;
101 let parsed_name = parse_name(name)?;
102
103 Ok(Command::Test { name: parsed_name, is_extension: parsed_optional_extension })
104}
105
106fn parse_optional_extension(optional_extension: Pair<'_, Rule>) -> ParseResult<bool, Rule> {
107 let extension_str = optional_extension.as_span().as_str();
108
109 match extension_str {
110 "" => Ok(false),
111 "+" => Ok(true),
112 c => Err(Box::new(ParseError::UnknownExtensionCharacter(c.to_string()))),
113 }
114}