at_commands/parser/
arguments_parser.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/// The functions in this module convert the untyped pest Pair syntax nodes to typed AT command argument nodes.
6///
7/// The types in the arguments module represent the arguments of either AT commands and responses.  However, the
8/// pest grammar macros generate different Rule types for the arguments of AT commands or responses.  Thus, the
9/// argument parser must be abstracted over the Rule types.  In addition, the actual enum variants of the Rule
10/// type differ between different generated macros, so we also abstract over the Rule enum values by storing them
11/// in a struct.
12///
13/// These functions should not fail, but report failures from the next_* methods if the
14/// expected element is not found.  This should only happen if the code here does not correctly
15/// match the parse tree defined in argument_grammar.rs.
16use {
17    crate::{
18        lowlevel::{Argument, Arguments, DelimitedArguments},
19        parser::common::{
20            next_match, next_match_one_of, next_match_option, next_match_rep, parse_string,
21            ParseResult,
22        },
23    },
24    pest::{iterators::Pair, RuleType},
25};
26
27pub struct ArgumentsParser<Rule: RuleType> {
28    pub argument_list: Rule,
29    pub argument: Rule,
30    pub arguments: Rule,
31    pub key_value_argument: Rule,
32    pub optional_argument_delimiter: Rule,
33    pub optional_argument_terminator: Rule,
34    pub parenthesized_argument_lists: Rule,
35    pub primitive_argument: Rule,
36}
37
38impl<Rule: RuleType> ArgumentsParser<Rule> {
39    #[allow(clippy::large_result_err)]
40    pub fn parse_delimited_arguments(
41        &self,
42        delimited_arguments: Pair<'_, Rule>,
43    ) -> ParseResult<DelimitedArguments, Rule> {
44        let mut delimited_arguments_elements = delimited_arguments.into_inner();
45
46        let delimited_argument_delimiter_option =
47            next_match_option(&mut delimited_arguments_elements, self.optional_argument_delimiter)?;
48        let parsed_delimited_argument_delimiter_option = match delimited_argument_delimiter_option {
49            Some(delimiter) => {
50                let string = parse_string(delimiter)?;
51                (!string.is_empty()).then_some(string)
52            }
53            None => None,
54        };
55
56        let arguments = next_match(&mut delimited_arguments_elements, self.arguments)?;
57        let parsed_arguments = self.parse_arguments(arguments)?;
58
59        let delimited_argument_terminator_option = next_match_option(
60            &mut delimited_arguments_elements,
61            self.optional_argument_terminator,
62        )?;
63        let parsed_delimited_argument_terminator_option = match delimited_argument_terminator_option
64        {
65            Some(terminator) => {
66                let string = parse_string(terminator)?;
67                (!string.is_empty()).then_some(string)
68            }
69            None => None,
70        };
71
72        Ok(DelimitedArguments {
73            delimiter: parsed_delimited_argument_delimiter_option,
74            arguments: parsed_arguments,
75            terminator: parsed_delimited_argument_terminator_option,
76        })
77    }
78
79    fn parse_arguments(&self, arguments: Pair<'_, Rule>) -> ParseResult<Arguments, Rule> {
80        let mut arguments_elements = arguments.into_inner();
81        let arguments_variant = next_match_one_of(
82            &mut arguments_elements,
83            vec![self.parenthesized_argument_lists, self.argument_list],
84        )?;
85        let arguments_variant_rule = arguments_variant.as_rule();
86        let parsed_arguments = if arguments_variant_rule == self.parenthesized_argument_lists {
87            self.parse_parenthesized_argument_lists(arguments_variant)?
88        } else if arguments_variant_rule == self.argument_list {
89            self.parse_argument_list(arguments_variant)?
90        } else {
91            // This is unreachable since next_match_one_of only returns success if one of the rules
92            // passed into it matches; otherwise it returns Err and this method will return early
93            // before reaching this point.
94            unreachable!()
95        };
96
97        Ok(parsed_arguments)
98    }
99
100    fn parse_parenthesized_argument_lists(
101        &self,
102        parenthesized_argument_lists: Pair<'_, Rule>,
103    ) -> ParseResult<Arguments, Rule> {
104        let mut parenthesized_argument_lists_elements = parenthesized_argument_lists.into_inner();
105        let argument_list_vec =
106            next_match_rep(&mut parenthesized_argument_lists_elements, self.argument_list);
107
108        let parsed_argument_list_vec = argument_list_vec
109            .into_iter()
110            .map(|argument_list_pair| self.parse_argument_list_to_vec(argument_list_pair))
111            .collect::<ParseResult<Vec<Vec<Argument>>, Rule>>()?;
112
113        Ok(Arguments::ParenthesisDelimitedArgumentLists(parsed_argument_list_vec))
114    }
115
116    fn parse_argument_list(&self, argument_list: Pair<'_, Rule>) -> ParseResult<Arguments, Rule> {
117        let parsed_argument_list = self.parse_argument_list_to_vec(argument_list)?;
118        Ok(Arguments::ArgumentList(parsed_argument_list))
119    }
120
121    fn parse_argument_list_to_vec(
122        &self,
123        argument_list: Pair<'_, Rule>,
124    ) -> ParseResult<Vec<Argument>, Rule> {
125        let mut argument_list_elements = argument_list.into_inner();
126        let argument_vec = next_match_rep(&mut argument_list_elements, self.argument);
127
128        let parsed_argument_vec = argument_vec
129            .into_iter()
130            .map(|argument_pair| self.parse_argument(argument_pair))
131            .collect::<ParseResult<Vec<Argument>, Rule>>()?;
132
133        // This is a hack.  There's no way for the parser to tell if "AT+CMD=" contains zero
134        // arguments or one empty argument.  The parser eagerly assumes that it's one empty
135        // argument.  However, if the AT command definition expects zero arguments this is an
136        // error. On the other hand, missing optional argunments at the end of an AT command
137        // are considered empty. Forcing this to be zero arguments here allows the raise step
138        // to handle both the zero arguments case and the empty optional argument case.
139        let parsed_argument_vec_maybe_empty =
140            if parsed_argument_vec == vec![Argument::PrimitiveArgument(String::from(""))] {
141                Vec::new()
142            } else {
143                parsed_argument_vec
144            };
145
146        Ok(parsed_argument_vec_maybe_empty)
147    }
148
149    fn parse_argument(&self, argument: Pair<'_, Rule>) -> ParseResult<Argument, Rule> {
150        let mut argument_elements = argument.into_inner();
151
152        let argument_variant = next_match_one_of(
153            &mut argument_elements,
154            vec![self.key_value_argument, self.primitive_argument],
155        )?;
156
157        let argument_variant_rule = argument_variant.as_rule();
158        let parsed_argument = if argument_variant_rule == self.key_value_argument {
159            self.parse_key_value_argument(argument_variant)?
160        } else if argument_variant_rule == self.primitive_argument {
161            Argument::PrimitiveArgument(parse_string(argument_variant)?)
162        } else {
163            // This is unreachable since next_match_one_of only returns success if one of the rules
164            // passed into it matches; otherwise it returns Err and this method will return early
165            // before reaching this point.
166            unreachable!()
167        };
168
169        Ok(parsed_argument)
170    }
171
172    fn parse_key_value_argument(
173        &self,
174        key_value_argument: Pair<'_, Rule>,
175    ) -> ParseResult<Argument, Rule> {
176        let mut argument_elements = key_value_argument.into_inner();
177
178        let key = next_match(&mut argument_elements, self.primitive_argument)?;
179        let parsed_key = parse_string(key)?;
180
181        let value = next_match(&mut argument_elements, self.primitive_argument)?;
182        let parsed_value = parse_string(value)?;
183
184        Ok(Argument::KeyValueArgument { key: parsed_key, value: parsed_value })
185    }
186}