nom-kconfig 0.9.0

A Kconfig parser
Documentation
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
use crate::{
    assert_parsing_eq, assert_parsing_fail,
    attribute::{
        expression::{
            parse_expression, AndExpression, Atom, CompareExpression, CompareOperand,
            CompareOperator, Expression, Term,
        },
        function::{ExpressionToken, FunctionCall, Parameter},
    },
    string::parse_string,
    symbol::{ConstantSymbol, Symbol},
};

#[test]
fn test_parse_expression_number() {
    assert_parsing_eq!(
        parse_expression,
        "-412",
        Ok((
            "",
            Expression::Term(AndExpression::Term(Term::Atom(Atom::Symbol(
                Symbol::Constant(ConstantSymbol::Integer(-412))
            ))))
        ))
    )
}

#[test]
fn test_parse_term() {
    assert_parsing_eq!(
        parse_expression,
        "!KVM",
        Ok((
            "",
            Expression::Term(AndExpression::Term(Term::Not(Atom::Symbol(
                Symbol::NonConstant("KVM".to_string())
            ))))
        ))
    )
}

#[test]
fn test_parse_depends_on_and() {
    assert_parsing_eq!(
        parse_expression,
        "ALPHA_MIATA && ALPHA_LX164",
        Ok((
            "",
            Expression::Term(AndExpression::Expression(vec!(
                Term::Atom(Atom::Symbol(Symbol::NonConstant("ALPHA_MIATA".to_string()))),
                Term::Atom(Atom::Symbol(Symbol::NonConstant("ALPHA_LX164".to_string()))),
            )))
        ))
    )
}

#[test]
fn test_parse_number_or_symbol() {
    assert_parsing_eq!(
        parse_expression,
        "64BITS",
        Ok((
            "",
            Expression::Term(AndExpression::Term(Term::Atom(Atom::Symbol(
                Symbol::NonConstant("64BITS".to_string()),
            ))))
        ))
    );
    assert_parsing_eq!(
        parse_expression,
        "64",
        Ok((
            "",
            Expression::Term(AndExpression::Term(Term::Atom(Atom::Symbol(
                Symbol::Constant(ConstantSymbol::Integer(64))
            )))),
        ))
    );

    assert_parsing_eq!(
        parse_expression,
        "\"64\"",
        Ok((
            "",
            Expression::Term(AndExpression::Term(Term::Atom(Atom::Symbol(
                Symbol::Constant(ConstantSymbol::String("64".to_string()))
            )))),
        ))
    );

    assert_parsing_eq!(
        parse_expression,
        "'64'",
        Ok((
            "",
            Expression::Term(AndExpression::Term(Term::Atom(Atom::Symbol(
                Symbol::Constant(ConstantSymbol::String("64".to_string()))
            )))),
        ))
    );
}

#[test]
fn test_parse_depends_on_ambigus() {
    assert_parsing_eq!(
        parse_expression,
        "ALPHA_MIATA || ALPHA_LX164 && ALPHA_SX164",
        Ok((
            "",
            Expression::Expression(vec!(
                AndExpression::Term(Term::Atom(Atom::Symbol(Symbol::NonConstant(
                    "ALPHA_MIATA".to_string()
                )))),
                AndExpression::Expression(vec!(
                    Term::Atom(Atom::Symbol(Symbol::NonConstant("ALPHA_LX164".to_string()))),
                    Term::Atom(Atom::Symbol(Symbol::NonConstant("ALPHA_SX164".to_string()))),
                ))
            ))
        ))
    )
}

// 5.0/scripts/gcc-plugins/Kconfig
#[test]
fn test_parse_string() {
    assert_parsing_eq!(
        parse_string,
        r#""hello "world"" if NET"#,
        Ok((" if NET", r#"hello "world""#.to_string()),)
    );

    assert_parsing_fail!(parse_string, r#""hello "world""#);

    assert_parsing_fail!(
        parse_string,
        r#""hello "world"
""#
    )
}

#[test]
fn test_parse_depends_on_optimization() {
    assert_parsing_eq!(
        parse_expression,
        "ALPHA_MIATA || ALPHA_LX164 && ALPHA_SX164 && (HELLO = world) || ALPHA_SX164 && (HELLO = world)",
        Ok(("", Expression::Expression(
            vec!(
                AndExpression::Term(Term::Atom(Atom::Symbol(Symbol::NonConstant("ALPHA_MIATA".to_string())))),
                AndExpression::Expression(vec!(
                    Term::Atom(Atom::Symbol(Symbol::NonConstant("ALPHA_LX164".to_string()))),
                    Term::Atom(Atom::Symbol(Symbol::NonConstant("ALPHA_SX164".to_string()))),
                    Term::Atom(Atom::Parenthesis(Box::new(Expression::Term(AndExpression::Term(Term::Atom(Atom::Compare(CompareExpression { left: CompareOperand::Symbol(Symbol::NonConstant("HELLO".to_string())), operator: CompareOperator::Equal, right: CompareOperand::Symbol(Symbol::NonConstant("world".to_string())) }))))))),
                )),
                AndExpression::Expression(vec!(
                    Term::Atom(Atom::Symbol(Symbol::NonConstant("ALPHA_SX164".to_string()))),
                    Term::Atom(Atom::Parenthesis(Box::new(Expression::Term(AndExpression::Term(Term::Atom(Atom::Compare(CompareExpression { left: CompareOperand::Symbol(Symbol::NonConstant("HELLO".to_string())), operator: CompareOperator::Equal, right: CompareOperand::Symbol(Symbol::NonConstant("world".to_string()))})))))))
                )
            )
        )))))
}

#[test]
fn test_parse_expression_function() {
    assert_parsing_eq!(
        parse_expression,
        "$(success,$(OBJCOPY) --version | head -n1 | grep -qv llvm)",
        Ok((
            "",
            Expression::Term(AndExpression::Term(Term::Atom(Atom::Function(
                FunctionCall {
                    name: "success".to_string(),
                    parameters: vec!(Parameter {
                        tokens: vec!(
                            ExpressionToken::Variable("OBJCOPY".to_string()),
                            ExpressionToken::Space,
                            ExpressionToken::Literal("--version".to_string()),
                            ExpressionToken::Space,
                            ExpressionToken::Literal("|".to_string()),
                            ExpressionToken::Space,
                            ExpressionToken::Literal("head".to_string()),
                            ExpressionToken::Space,
                            ExpressionToken::Literal("-n1".to_string()),
                            ExpressionToken::Space,
                            ExpressionToken::Literal("|".to_string()),
                            ExpressionToken::Space,
                            ExpressionToken::Literal("grep".to_string()),
                            ExpressionToken::Space,
                            ExpressionToken::Literal("-qv".to_string()),
                            ExpressionToken::Space,
                            ExpressionToken::Literal("llvm".to_string())
                        )
                    })
                }
            ))))
        ))
    )
}

// v3.6-rc4/drivers/mtd/maps/Kconfig
#[test]
fn test_parse_expression_start_like_number_but_symbol() {
    assert_parsing_eq!(
        parse_expression,
        r#"8xx && MTD_CFI"#,
        Ok((
            "",
            Expression::Term(AndExpression::Expression(vec!(
                Term::Atom(Atom::Symbol(Symbol::NonConstant("8xx".to_string()))),
                Term::Atom(Atom::Symbol(Symbol::NonConstant("MTD_CFI".to_string()))),
            )))
        ))
    )
}

#[test]
fn test_parse_expression_number_and() {
    assert_parsing_eq!(
        parse_expression,
        r#"8500 && MTD_CFI"#,
        Ok((
            "",
            Expression::Term(AndExpression::Expression(vec!(
                Term::Atom(Atom::Symbol(Symbol::Constant(ConstantSymbol::Integer(
                    8500
                )))),
                Term::Atom(Atom::Symbol(Symbol::NonConstant("MTD_CFI".to_string()))),
            )))
        ))
    )
}

#[test]
fn test_expression_to_string() {
    assert_eq!(
        "NUMBER_OF_PROCS = 5",
        Expression::Term(AndExpression::Term(Term::Atom(Atom::Compare(
            CompareExpression {
                left: CompareOperand::Symbol(Symbol::NonConstant("NUMBER_OF_PROCS".to_string())),
                operator: CompareOperator::Equal,
                right: CompareOperand::Symbol(Symbol::Constant(ConstantSymbol::Integer(5)))
            }
        ))))
        .to_string()
    );
    assert_eq!(
        "NUMBER_OF_PROCS != 5",
        Expression::Term(AndExpression::Term(Term::Atom(Atom::Compare(
            CompareExpression {
                left: CompareOperand::Symbol(Symbol::NonConstant("NUMBER_OF_PROCS".to_string())),
                operator: CompareOperator::NotEqual,
                right: CompareOperand::Symbol(Symbol::Constant(ConstantSymbol::Integer(5)))
            }
        ))))
        .to_string()
    );
    assert_eq!(
        "NUMBER_OF_PROCS < 5",
        Expression::Term(AndExpression::Term(Term::Atom(Atom::Compare(
            CompareExpression {
                left: CompareOperand::Symbol(Symbol::NonConstant("NUMBER_OF_PROCS".to_string())),
                operator: CompareOperator::LowerThan,
                right: CompareOperand::Symbol(Symbol::Constant(ConstantSymbol::Integer(5)))
            }
        ))))
        .to_string()
    );
    assert_eq!(
        "NUMBER_OF_PROCS <= 5",
        Expression::Term(AndExpression::Term(Term::Atom(Atom::Compare(
            CompareExpression {
                left: CompareOperand::Symbol(Symbol::NonConstant("NUMBER_OF_PROCS".to_string())),
                operator: CompareOperator::LowerOrEqual,
                right: CompareOperand::Symbol(Symbol::Constant(ConstantSymbol::Integer(5)))
            }
        ))))
        .to_string()
    );
    assert_eq!(
        "NUMBER_OF_PROCS > 5",
        Expression::Term(AndExpression::Term(Term::Atom(Atom::Compare(
            CompareExpression {
                left: CompareOperand::Symbol(Symbol::NonConstant("NUMBER_OF_PROCS".to_string())),
                operator: CompareOperator::GreaterThan,
                right: CompareOperand::Symbol(Symbol::Constant(ConstantSymbol::Integer(5)))
            }
        ))))
        .to_string()
    );
    assert_eq!(
        r#""A string with "double quotes"""#,
        Expression::Term(AndExpression::Term(Term::Atom(Atom::Symbol(
            Symbol::Constant(ConstantSymbol::String(
                r#"A string with "double quotes""#.to_string()
            ))
        ))))
        .to_string()
    );
    assert_eq!(
        "NUMBER_OF_PROCS >= 5",
        Expression::Term(AndExpression::Term(Term::Atom(Atom::Compare(
            CompareExpression {
                left: CompareOperand::Symbol(Symbol::NonConstant("NUMBER_OF_PROCS".to_string())),
                operator: CompareOperator::GreaterOrEqual,
                right: CompareOperand::Symbol(Symbol::Constant(ConstantSymbol::Integer(5)))
            }
        ))))
        .to_string()
    );
    assert_eq!(
        "KVM && NET",
        Expression::Term(AndExpression::Expression(vec!(
            Term::Atom(Atom::Symbol(Symbol::NonConstant("KVM".to_string()))),
            Term::Atom(Atom::Symbol(Symbol::NonConstant("NET".to_string())))
        )))
        .to_string()
    );
    assert_eq!(
        "KVM || NET",
        Expression::Expression(vec!(
            AndExpression::Term(Term::Atom(Atom::Symbol(Symbol::NonConstant(
                "KVM".to_string()
            )))),
            AndExpression::Term(Term::Atom(Atom::Symbol(Symbol::NonConstant(
                "NET".to_string()
            ))))
        ))
        .to_string()
    );
    assert_eq!(
        "!KVM",
        Expression::Term(AndExpression::Term(Term::Not(Atom::Symbol(
            Symbol::NonConstant("KVM".to_string())
        ))))
        .to_string()
    );
    assert_eq!(
        "55",
        Expression::Term(AndExpression::Term(Term::Atom(Atom::Symbol(
            Symbol::Constant(ConstantSymbol::Integer(55))
        ))))
        .to_string()
    );
    assert_eq!(
        r#"(hello)"#,
        Expression::Term(AndExpression::Term(Term::Atom(Atom::Parenthesis(
            Box::new(Expression::Term(AndExpression::Term(Term::Atom(
                Atom::Symbol(Symbol::NonConstant("hello".to_string()))
            ))))
        ))))
        .to_string()
    );
    assert_eq!(
        "$(warning)",
        Expression::Term(AndExpression::Term(Term::Atom(Atom::Function(
            FunctionCall {
                name: "warning".to_string(),
                parameters: vec!()
            }
        ))))
        .to_string()
    );
}

// https://github.com/Mcdostone/nom-kconfig/issues/107#issuecomment-3703986206

#[test]
fn test_expression_constant_and_non_constant() {
    assert_parsing_eq!(
        parse_expression,
        "MTD!=n",
        Ok((
            "",
            Expression::Term(AndExpression::Term(Term::Atom(Atom::Compare(
                CompareExpression {
                    left: CompareOperand::Symbol(Symbol::NonConstant("MTD".to_string())),
                    operator: CompareOperator::NotEqual,
                    right: CompareOperand::Symbol(Symbol::Constant(ConstantSymbol::Boolean(false)))
                }
            ))))
        ))
    )
}

// https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/init/Kconfig?h=next-20260403#n91
#[test]
#[cfg(feature = "coreboot")]
fn test_expression_compare_with_function_call() {
    assert_parsing_eq!(
        parse_expression,
        "CC_IS_CLANG && RUSTC_LLVM_MAJOR_VERSION = $(shell,expr $(cc-version) / 10000)",
        Ok((
            "",
            Expression::Term(AndExpression::Expression(vec!(
                Term::Atom(Atom::Symbol(Symbol::NonConstant("CC_IS_CLANG".to_string()))),
                Term::Atom(Atom::Compare(CompareExpression {
                    left: CompareOperand::Symbol(Symbol::NonConstant(
                        "RUSTC_LLVM_MAJOR_VERSION".to_string()
                    )),
                    operator: CompareOperator::Equal,
                    right: CompareOperand::Macro(FunctionCall {
                        name: "shell".to_string(),
                        parameters: vec!(Parameter {
                            tokens: vec!(
                                ExpressionToken::Literal("expr".to_string()),
                                ExpressionToken::Space,
                                ExpressionToken::Function(Box::new(FunctionCall {
                                    name: "cc-version".to_string(),
                                    parameters: vec![]
                                })),
                                ExpressionToken::Space,
                                ExpressionToken::Literal("/".to_string()),
                                ExpressionToken::Space,
                                ExpressionToken::Literal("10000".to_string())
                            )
                        })
                    })
                }))
            )))
        ))
    )
}

#[test]
/// https://github.com/u-boot/u-boot/blob/master/arch/arm/Kconfig#L2239
fn test_expression_compare_with_string() {
    assert_parsing_eq!(
        parse_expression,
        "DEFAULT_DEVICE_TREE = \"sun7i-a20-icnova-swac\"",
        Ok((
            "",
            Expression::Term(AndExpression::Term(Term::Atom(Atom::Compare(
                CompareExpression {
                    left: CompareOperand::Symbol(Symbol::NonConstant(
                        "DEFAULT_DEVICE_TREE".to_string()
                    )),
                    operator: CompareOperator::Equal,
                    right: CompareOperand::Symbol(Symbol::Constant(ConstantSymbol::String(
                        "sun7i-a20-icnova-swac".to_string()
                    )))
                }
            ))))
        ))
    )
}