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
macro_rules! logging_parts {
    (
        $write_target:expr; <==
            $literal:literal-$expression:expr
            $(=> $sub_literal:literal-$sub_expression:expr)*
            $(=> * $ending_literal:literal)?
                $(
                    , $next_literal:literal-$next_expression:expr
                    $(=> $next_sub_literal:literal-$next_sub_expression:expr)*
                    $(=> * $next_ending_literal:literal)?
                )*
                    $(,)?
            
    ) => {
        {
            use {
                paste::paste,
                // std::io::Write,
            };
            logging_parts!(
                @impl $write_target; <== reduce_type: top; current_ident: b1;
                $literal-$expression
                    $(=> $sub_literal-$sub_expression)*
                    $(=> * $ending_literal)?
                        $(
                            , $next_literal-$next_expression
                            $(=> $next_sub_literal-$next_sub_expression)*
                            $(=> * $next_ending_literal)?
                        )*
                ; >-< [] []
            )
        }
        
    };
    
    (
        @impl $write_target:expr; <==
        reduce_type: top; current_ident: $current_ident:ident;
            $literal:literal-$expression:expr
            $(=> $sub_literal:literal-$sub_expression:expr)*
            $(=> * $ending_literal:literal)?
                $(
                    , $next_literal:literal-$next_expression:expr
                    $(=> $next_sub_literal:literal-$next_sub_expression:expr)*
                    $(=> * $next_ending_literal:literal)?
                )*;
            >-< [$($literals:literal)*] [$($idents:ident)*] 
    ) => {
        match $expression {
            Some($current_ident) => paste! {
                logging_parts!(
                    @impl $write_target; <== reduce_type: sub; current_ident: [<$current_ident _s>];
                    $(=> $sub_literal-$sub_expression)*
                    $(=> * $ending_literal)?;
                    >-< [$($literals)* $literal] [$($idents)* $current_ident];
                    next_up:
                        $(
                            $next_literal-$next_expression
                            $(=> $next_sub_literal-$next_sub_expression)*
                            $(=> * $next_ending_literal)?
                        ),*
                )
            },
            None => paste! {
                logging_parts!(
                    @impl $write_target; <== reduce_type: top; current_ident: [<$current_ident 1>];
                        $(
                            $next_literal-$next_expression
                            $(=> $next_sub_literal-$next_sub_expression)*
                            $(=> * $next_ending_literal)?
                        ),*;
                     >-< [$($literals)*] [$($idents)*]
                )
            },
        }
    };

    (
        @impl $write_target:expr; <==
        reduce_type: top; current_ident: $current_ident:ident; ;
        >-< [$($literals:literal)*] [$($idents:ident)*]
    ) => {
        $write_target.write_fmt(format_args!(concat!(concat!("", $($literals),*), "\n"), $($idents),*))
    };


    (
        @impl $write_target:expr; <==
            reduce_type: sub; current_ident: $current_ident:ident;
                => $sub_literal:literal - $sub_expression:expr $(=> $next_sub_literal:literal - $next_sub_expression:expr)*
                $(=> * $ending_literal:literal)?;
                >-< [$($literals:literal)+] [$($idents:ident)+];
                next_up:
                    $(
                        $next_next_literal:literal-$next_next_expression:expr
                        $(=> $next_next_sub_literal:literal-$next_next_sub_expression:expr)*
                        $(=> * $next_next_ending_literal:literal)?
                    ),*
    ) => {
        match $sub_expression {
            Some($current_ident) => paste!{
                logging_parts!(
                    @impl $write_target; <== reduce_type: sub; current_ident: [<$current_ident _s>];
                    $(=> $next_sub_literal-$next_sub_expression)* $(=> * $ending_literal)?;
                    >-< [$($literals)+ $sub_literal] [$($idents)+ $current_ident];
                    next_up:
                        $(
                            $next_next_literal-$next_next_expression
                            $(=> $next_next_sub_literal-$next_next_sub_expression)*
                            $(=> * $next_next_ending_literal)?
                        ),*
                )
            },
            None => logging_parts!(
                @impl $write_target; <== reduce_type: sub; current_ident: $current_ident;
                $(=> * $ending_literal)?;
                >-< [$($literals)+] [$($idents)*];
                next_up:
                    $(
                        $next_next_literal-$next_next_expression
                        $(=> $next_next_sub_literal-$next_next_sub_expression)*
                        $(=> * $next_next_ending_literal)?
                    ),*
            ),
        }
    };

    (
        @impl $write_target:expr; <==
            reduce_type: sub; current_ident: $current_ident:ident; => * $ending_literal:literal;
            >-< [$($literals:literal)+] [$($idents:ident)+];
            next_up:
                $(
                    $next_literal:literal-$next_expression:expr
                    $(=> $next_sub_literal:literal-$next_sub_expression:expr)*
                    $(=> * $next_ending_literal:literal)?
                ),*
    ) => {
        logging_parts!(
            @impl $write_target; <==
                reduce_type: sub; current_ident: $current_ident; ;
                >-< [$($literals)+ $ending_literal] [$($idents)+];
                next_up:
                    $(
                        $next_literal-$next_expression
                        $(=> $next_sub_literal-$next_sub_expression)*
                        $(=> * $next_ending_literal)?
                    ),*
        )
    };

    (
        @impl $write_target:expr; <==
            reduce_type: sub; current_ident: $current_ident:ident; ;
            >-< [$($literals:literal)*] [$($idents:ident)*]; 
            next_up:
                $(
                    $next_literal:literal-$next_expression:expr
                    $(=> $next_sub_literal:literal-$next_sub_expression:expr)*
                    $(=> * $next_ending_literal:literal)?
                ),*
    ) => {
        paste! {
            logging_parts!(
                @impl $write_target; <== reduce_type: top; current_ident: [<$current_ident _b1>];
                    $(
                        $next_literal-$next_expression
                        $(=> $next_sub_literal-$next_sub_expression)*
                        $(=> * $next_ending_literal)?
                    ),*;
                 >-< [$($literals)*] [$($idents)*]
            )
        }
    };
}

pub (crate) use logging_parts;