ldscript_parser/
script.rs

1use commands::{command, Command};
2use memory::region;
3use memory::Region;
4use nom::branch::alt;
5use nom::bytes::complete::tag;
6use nom::combinator::map;
7use nom::multi::many1;
8use nom::sequence::tuple;
9use nom::IResult;
10use sections::section_command;
11use sections::SectionCommand;
12use statements::{statement, Statement};
13use whitespace::opt_space;
14
15#[derive(Debug, PartialEq)]
16pub enum RootItem {
17    Statement(Statement),
18    Command(Command),
19    Memory { regions: Vec<Region> },
20    Sections { list: Vec<SectionCommand> },
21}
22
23fn statement_item(input: &str) -> IResult<&str, RootItem> {
24    map(statement, |stmt| RootItem::Statement(stmt))(input)
25}
26
27fn command_item(input: &str) -> IResult<&str, RootItem> {
28    map(command, |cmd| RootItem::Command(cmd))(input)
29}
30
31fn memory_item(input: &str) -> IResult<&str, RootItem> {
32    let (input, _) = tuple((tag("MEMORY"), wsc!(tag("{"))))(input)?;
33    let (input, regions) = many1(wsc!(region))(input)?;
34    let (input, _) = tag("}")(input)?;
35    Ok((input, RootItem::Memory { regions: regions }))
36}
37
38fn sections_item(input: &str) -> IResult<&str, RootItem> {
39    let (input, _) = tuple((tag("SECTIONS"), wsc!(tag("{"))))(input)?;
40    let (input, sections) = many1(wsc!(section_command))(input)?;
41    let (input, _) = tag("}")(input)?;
42    Ok((input, RootItem::Sections { list: sections }))
43}
44
45fn root_item(input: &str) -> IResult<&str, RootItem> {
46    alt((statement_item, memory_item, sections_item, command_item))(input)
47}
48
49pub fn parse(input: &str) -> IResult<&str, Vec<RootItem>> {
50    alt((many1(wsc!(root_item)), map(opt_space, |_| vec![])))(input)
51}
52
53#[cfg(test)]
54mod tests {
55    use script::*;
56    use std::fs::{self, File};
57    use std::io::Read;
58
59    #[test]
60    fn test_empty() {
61        assert_done_vec!(parse(""), 0);
62        assert_done_vec!(parse("                               "), 0);
63        assert_done_vec!(parse("      /* hello */              "), 0);
64    }
65
66    #[test]
67    fn test_parse() {
68        for entry in fs::read_dir("tests").unwrap() {
69            let path = entry.unwrap().path();
70            println!("testing: {:?}", path);
71            let mut file = File::open(path).unwrap();
72            let mut contents = String::new();
73            file.read_to_string(&mut contents).unwrap();
74            assert_done!(parse(&contents));
75        }
76    }
77}