nom_config_in/
symbol.rs

1use nom::{
2    branch::alt,
3    bytes::complete::{tag, take_until},
4    character::complete::char,
5    character::complete::{alphanumeric1, one_of},
6    combinator::{map, recognize},
7    multi::many1,
8    sequence::{delimited, preceded},
9    IResult,
10};
11
12use crate::ConfigInInput;
13
14use super::util::ws;
15
16/// There are two types of symbols: constant and non-constant symbols. Non-constant symbols are the most
17/// common ones and are defined with the 'config' statement. Non-constant symbols consist entirely of al-
18/// phanumeric characters or underscores. Constant symbols are only part of expressions. Constant symbols
19/// are always surrounded by single or double quotes. Within the quote, any other character is allowed and
20/// the quotes can be escaped using ''.
21pub type Symbol = String;
22
23pub fn parse_symbol(input: ConfigInInput) -> IResult<ConfigInInput, Symbol> {
24    alt((
25        map(parse_constant_symbol, |c: ConfigInInput| c.to_string()),
26        map(
27            delimited(ws(char('"')), take_until("\""), char('"')),
28            |c: ConfigInInput| format!("\"{}\"", c),
29        ),
30        map(
31            delimited(ws(char('\'')), take_until("'"), char('\'')),
32            |c: ConfigInInput| format!("'{}'", c),
33        ),
34    ))(input)
35}
36
37pub fn parse_constant_symbol(input: ConfigInInput) -> IResult<ConfigInInput, ConfigInInput> {
38    map(
39        recognize(many1(alt((alphanumeric1, recognize(one_of(",._-/$+")))))),
40        |c: ConfigInInput| c,
41    )(input)
42}
43
44pub fn parse_constant_symbol_or_variable(input: ConfigInInput) -> IResult<ConfigInInput, String> {
45    alt((
46        map(preceded(tag("$"), parse_constant_symbol), |f| {
47            format!("${}", f)
48        }),
49        map(parse_symbol, |d| d.to_string()),
50    ))(input)
51}