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
#[macro_export]
macro_rules! java_inner {
    (toplevel { package $name:ident; $($remaining:tt) * }) => {
        java_inner!(toplevel { $($remaining) * });
    };
    (toplevel { public class $name:ident {
        $($inner:tt) *
    } $($remaining:tt) * }) => {
        pub struct $name {
        }
        java_inner!(class($name) { $($inner) * });
        java_inner!(toplevel { $($remaining) * });
    };
    (toplevel { class $name:ident {
        $($inner:tt) *
    } $($remaining:tt) * }) => {
        struct $name {
        }
        java_inner!(class($name) { $($inner) * });
        java_inner!(toplevel { $($remaining) * });
    };
    (toplevel {}) => {};

    (class($name:ident) { public static void main(String[] $args:ident) {
        $($inner:tt) *
    } $($remaining:tt) * }) => {
        fn main() {
            let mut $args: Vec<String> = std::env::args().skip(1).collect();
            java_inner!(stmt { $($inner) * });
        }
        java_inner!(toplevel { $($remaining) * });
    };
    (class($name:ident) {}) => {};

    (stmt { System.out.println($($out:expr) *); $($remaining:tt) * }) => {
        $(
            print!("{} ", $out);
        ) *
        println!();
        java_inner!(stmt { $($remaining) * })
    };
    (stmt { System.out.println_debug($($out:expr) *); $($remaining:tt) * }) => {
        $(
            print!("{:?} ", $out);
        ) *
        println!();
        java_inner!(stmt { $($remaining) * });
    };
    (stmt { $type:ident $name:ident = $value:expr; $($remaining:tt) * }) => {
        let mut $name: java_inner!(kind $type) = $value;
        java_inner!(stmt { $($remaining) * });
    };
    (stmt { $name:ident++; $($remaining:tt) * }) => {
        $name += 1;
        java_inner!(stmt { $($remaining) * });
    };
    (stmt { for (($($pre:tt) *) $cond:expr; ($($post:tt) *)) {
        $($inner:tt) *
    } $($remaining:tt) * }) => {
        java_inner!(stmt { $($pre) * });
        loop {
            if !$cond {
                break;
            }
            java_inner!(stmt { $($inner) * });
            java_inner!(stmt { $($post) * });
        }
        java_inner!(stmt { $($remaining) * });
    };
    (stmt {}) => {};
    (kind int) => { i32 };
}
#[macro_export]
macro_rules! java {
    ($($code:tt) *) => {
        java_inner!(toplevel { $($code) * });
    }
}