nom_kconfig/
symbol.rs

1use nom::{
2    branch::alt,
3    bytes::complete::take_until,
4    character::complete::{alphanumeric1, char, one_of},
5    combinator::{map, recognize},
6    multi::many1,
7    sequence::delimited,
8    IResult, Parser,
9};
10#[cfg(feature = "deserialize")]
11use serde::Deserialize;
12#[cfg(feature = "serialize")]
13use serde::Serialize;
14
15use crate::KconfigInput;
16
17use super::util::ws;
18
19/// There are two types of symbols: constant and non-constant symbols. Non-constant symbols are the most
20/// common ones and are defined with the 'config' statement. Non-constant symbols consist entirely of al-
21/// phanumeric characters or underscores. Constant symbols are only part of expressions. Constant symbols
22/// are always surrounded by single or double quotes. Within the quote, any other character is allowed and
23/// the quotes can be escaped using ''.
24#[derive(Debug, PartialEq, Clone)]
25#[cfg_attr(feature = "hash", derive(Hash))]
26#[cfg_attr(feature = "serialize", derive(Serialize))]
27#[cfg_attr(feature = "deserialize", derive(Deserialize))]
28pub enum Symbol {
29    Constant(String),
30    NonConstant(String),
31}
32
33pub fn parse_symbol(input: KconfigInput) -> IResult<KconfigInput, Symbol> {
34    alt((
35        map(parse_constant_symbol, |c: &str| {
36            Symbol::Constant(c.to_string())
37        }),
38        map(
39            delimited(ws(char('"')), take_until("\""), char('"')),
40            |c: KconfigInput| Symbol::NonConstant(format!("\"{}\"", c)),
41        ),
42        map(
43            delimited(ws(char('\'')), take_until("'"), char('\'')),
44            |c: KconfigInput| Symbol::NonConstant(format!("'{}'", c)),
45        ),
46    ))
47    .parse(input)
48}
49
50pub fn parse_constant_symbol(input: KconfigInput<'_>) -> IResult<KconfigInput<'_>, &str> {
51    map(
52        recognize(ws(many1(alt((alphanumeric1, recognize(one_of("._"))))))),
53        |c: KconfigInput| c.trim(),
54    )
55    .parse(input)
56}
57
58#[cfg(feature = "display")]
59use std::fmt::Display;
60#[cfg(feature = "display")]
61impl Display for Symbol {
62    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
63        match self {
64            Symbol::Constant(c) => write!(f, "{}", c),
65            Symbol::NonConstant(c) => write!(f, "\"{}\"", c),
66        }
67    }
68}