1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use nom::{
    branch::alt,
    bytes::complete::tag,
    character::complete::{alphanumeric1, one_of},
    combinator::{map, recognize},
    multi::many1,
    sequence::tuple,
    IResult,
};
#[cfg(feature = "deserialize")]
use serde::Deserialize;
#[cfg(feature = "serialize")]
use serde::Serialize;

use crate::{
    attribute::function::{parse_expression_token_variable_parameter, ExpressionToken},
    util::{parse_until_eol, ws},
    KconfigInput,
};

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "hash", derive(Hash))]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct VariableAssignment {
    pub identifier: VariableIdentifier,
    pub operator: String,
    pub right: Value,
}

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "hash", derive(Hash))]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum VariableIdentifier {
    Identifier(String),
    VariableRef(Vec<ExpressionToken>),
}

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "hash", derive(Hash))]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum Value {
    Literal(String),
    ExpandedVariable(String),
}

pub fn parse_value(input: KconfigInput) -> IResult<KconfigInput, Value> {
    map(parse_until_eol, |d| {
        Value::Literal(d.fragment().trim().to_string())
    })(input)
}

pub fn parse_variable_identifier(input: KconfigInput) -> IResult<KconfigInput, VariableIdentifier> {
    alt((
        map(
            recognize(ws(many1(alt((alphanumeric1, recognize(one_of("-_"))))))),
            |l: KconfigInput| VariableIdentifier::Identifier(l.trim().to_string()),
        ),
        map(many1(parse_expression_token_variable_parameter), |v| {
            VariableIdentifier::VariableRef(v)
        }),
    ))(input)
}

pub fn parse_variable_assignment(input: KconfigInput) -> IResult<KconfigInput, VariableAssignment> {
    map(
        tuple((
            ws(parse_variable_identifier),
            ws(parse_assign),
            ws(parse_value),
        )),
        |(l, o, r)| VariableAssignment {
            identifier: l,
            operator: o.to_string(),
            right: r,
        },
    )(input)
}

pub fn parse_assign(input: KconfigInput) -> IResult<KconfigInput, &str> {
    map(alt((tag("="), tag(":="), tag("+="))), |d: KconfigInput| {
        d.fragment().to_owned()
    })(input)
}