nom_kconfig/
symbol.rs

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