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
extern crate cc;
extern crate proc_macro2;
extern crate syn;

use std::path::{Path, PathBuf};
use syn::Item;

mod generate;
mod extract;
use extract::extract_asm;

use std::fs::{read_dir, File};
use std::io::Read;
use std::env;

#[macro_export]
macro_rules! lasm {
    ($abi:tt fn $name:tt {
        $($dontcare:tt)*
    } $($more:tt)*) => (lasm!($($more)*););

    () => {};
}

#[derive(Clone, Debug, PartialEq)]
pub struct Asm {
    pub name: String,
    pub body: Vec<String>,
}

pub fn parse_file(code: String) {
    let syntax = syn::parse_file(&code).expect("Unable to parse file");
    for item in syntax.items {
        match item {
            Item::Macro(macro_item) => {
                let mac = macro_item.mac;
                if mac.path == "lasm".into() {
                    extract_asm(mac.tts);
                }
            }
            _ => {}
        }
    }
}

pub fn parse_dir(dir: &Path) {
    for item in read_dir(dir).unwrap() {
        match item {
            Ok(item) => {
                let item_type = item.file_type().unwrap();
                if item_type.is_dir() {
                    parse_dir(&item.path())
                } else if item.path().to_str().unwrap().ends_with(".rs") {
                    let mut file = File::open(item.path()).unwrap();
                    let mut content = String::new();
                    file.read_to_string(&mut content).unwrap();
                    parse_file(content);
                }
            }
            _ => println!("cargo:warning=unable to read all source files"),
        }
    }
}

pub fn parse() {
    let dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("src");
    parse_dir(&dir);
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}