Skip to main content

step_p21/parser/exchange/
parameter.rs

1use crate::{
2    ast::*,
3    parser::{combinator::*, token::*},
4};
5use nom::{Parser, branch::alt, combinator::value};
6
7/// list = `(` \[ [parameter] { `,` [parameter] } \] `)` .
8pub fn list(input: &str) -> ParseResult<'_, Parameter> {
9    tuple_((char_('('), opt_(comma_separated(parameter)), char_(')')))
10        .map(|(_open, params, _close)| {
11            Parameter::List(params.unwrap_or_default())
12        })
13        .parse(input)
14}
15
16/// parameter = [typed_parameter] | [untyped_parameter] | [omitted_parameter] .
17pub fn parameter(input: &str) -> ParseResult<'_, Parameter> {
18    alt((typed_parameter, untyped_parameter, omitted_parameter)).parse(input)
19}
20
21/// typed_parameter = [keyword] `(` [parameter] `)` .
22pub fn typed_parameter(input: &str) -> ParseResult<'_, Parameter> {
23    tuple_((keyword, char_('('), parameter, char_(')')))
24        .map(|(name, _open, ty, _close)| Parameter::Typed {
25            keyword: name,
26            parameter: Box::new(ty),
27        })
28        .parse(input)
29}
30
31/// untyped_parameter = `$` | [integer] | [real] | [string] |
32/// [rhs_occurrence_name] | [enumeration] | binary | [list] .
33pub fn untyped_parameter(input: &str) -> ParseResult<'_, Parameter> {
34    alt((
35        char_('$').map(|_| Parameter::NotProvided),
36        real.map(Parameter::Real),
37        integer.map(Parameter::Integer),
38        string.map(Parameter::String),
39        rhs_occurrence_name.map(Parameter::Ref),
40        enumeration.map(Parameter::Enumeration),
41        // FIXME binary
42        list,
43    ))
44    .parse(input)
45}
46
47/// omitted_parameter = `*` .
48pub fn omitted_parameter(input: &str) -> ParseResult<'_, Parameter> {
49    value(Parameter::Omitted, char_('*')).parse(input)
50}
51
52/// parameter_list = [parameter] { `,` [parameter] } .
53pub fn parameter_list(input: &str) -> ParseResult<'_, Vec<Parameter>> {
54    comma_separated(parameter).parse(input)
55}
56
57#[cfg(test)]
58mod tests {
59    use crate::ast::Parameter;
60    use nom::Finish;
61
62    #[test]
63    fn untyped_parameter() {
64        let (res, record) = super::untyped_parameter("2").finish().unwrap();
65        assert_eq!(res, "");
66        assert_eq!(record, Parameter::integer(2));
67
68        let (res, record) = super::untyped_parameter("2.0").finish().unwrap();
69        assert_eq!(res, "");
70        assert_eq!(record, Parameter::real(2.0));
71    }
72
73    #[test]
74    fn parameter_list() {
75        let (res, record) =
76            super::untyped_parameter("(1, 2, 3)").finish().unwrap();
77        assert_eq!(res, "");
78        assert_eq!(
79            record,
80            Parameter::List(vec![
81                Parameter::Integer(1),
82                Parameter::Integer(2),
83                Parameter::Integer(3),
84            ])
85        );
86    }
87
88    #[test]
89    fn empty_parameter_list() {
90        let (res, record) = super::untyped_parameter("()").finish().unwrap();
91        assert_eq!(res, "");
92        assert_eq!(record, Parameter::List(vec![]));
93    }
94}