ldscript_parser/
commands.rs

1use expressions::expression;
2use expressions::Expression;
3use idents::{pattern, symbol};
4use nom::branch::alt;
5use nom::bytes::complete::tag;
6use nom::combinator::map;
7use nom::combinator::opt;
8use nom::multi::separated_list1;
9use nom::sequence::pair;
10use nom::IResult;
11use whitespace::{opt_space, space};
12
13#[derive(Debug, PartialEq)]
14pub enum InsertOrder {
15    Before,
16    After,
17}
18
19#[derive(Debug, PartialEq)]
20pub enum Command {
21    //Simple { name: String },
22    Call {
23        name: String,
24        arguments: Vec<Expression>,
25    },
26    Include {
27        file: String,
28    },
29    Insert {
30        order: InsertOrder,
31        section: String,
32    },
33}
34
35fn inset_order(input: &str) -> IResult<&str, InsertOrder> {
36    alt((
37        map(tag("BEFORE"), |_| InsertOrder::Before),
38        map(tag("AFTER"), |_| InsertOrder::After),
39    ))(input)
40}
41
42fn call(input: &str) -> IResult<&str, Command> {
43    let (input, name) = symbol(input)?;
44    let (input, _) = wsc!(tag("("))(input)?;
45    let (input, args) = separated_list1(alt((space, wsc!(tag(",")))), expression)(input)?;
46    let (input, _) = pair(wsc!(tag(")")), opt(tag(";")))(input)?;
47    Ok((
48        input,
49        Command::Call {
50            name: name.into(),
51            arguments: args,
52        },
53    ))
54}
55
56fn include(input: &str) -> IResult<&str, Command> {
57    let (input, _) = pair(tag("INCLUDE"), space)(input)?;
58    let (input, file) = pattern(input)?;
59    let (input, _) = pair(opt_space, opt(tag(";")))(input)?;
60    Ok((input, Command::Include { file: file.into() }))
61}
62
63fn insert(input: &str) -> IResult<&str, Command> {
64    let (input, _) = tag("INSERT")(input)?;
65    let (input, order) = wsc!(inset_order)(input)?;
66    let (input, section) = symbol(input)?;
67    let (input, _) = pair(opt_space, opt(tag(";")))(input)?;
68    Ok((
69        input,
70        Command::Insert {
71            order,
72            section: section.into(),
73        },
74    ))
75}
76
77pub fn command(input: &str) -> IResult<&str, Command> {
78    alt((include, call, insert))(input)
79}
80
81#[cfg(test)]
82mod tests {
83    use commands::*;
84
85    #[test]
86    fn test_command() {
87        assert_done!(command("OUTPUT_ARCH ( 0 ) ;"));
88        assert_done!(command("OUTPUT_ARCH ( 0 )"));
89        assert_done!(command("OUTPUT_ARCH ( 0 1 2 )"));
90        assert_done!(command("OUTPUT_ARCH ( 0, 1 2 )"));
91        assert_done!(command("OUTPUT_ARCH ( 0, 1, 2 )"));
92
93        assert_fail!(command("OUTPUT_ARCH ( 0, 1, 2, )"));
94        assert_fail!(command("OUTPUT_ARCH ( )"));
95
96        assert_done!(command("INCLUDE abc.h ;"));
97        assert_done!(command("INCLUDE\tabc.h"));
98
99        assert_done!(command("INSERT BEFORE .text  ;"));
100        assert_done!(command("INSERT  AFTER  .text"));
101    }
102}