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
#[macro_use]
mod ch_sequence;

macro_rules! arm_pattern {
    ( | $cb_args:tt |>
         alpha => $actions:tt
    ) => {
        state_body!(@callback | $cb_args |> Some(b'a'..=b'z') | Some(b'A'..=b'Z') => $actions);
    };

    ( | $cb_args:tt |>
        whitespace => $actions:tt
    ) => {
        state_body!(@callback | $cb_args |>
            Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') | Some(b'\x0C') => $actions
        );
    };

    ( | [ [$self:tt, $input_chunk:ident, $ch:ident ], $($rest_cb_args:tt)+ ] |>
        closing_quote => $actions:tt
    ) => {
        state_body!(@callback | [ [$self, $input_chunk, $ch], $($rest_cb_args)+ ] |>
            Some(ch) if ch == $self.closing_quote() => $actions
        );
    };


    ( | [ [$self:tt, $input:ident, $ch:ident ], $($rest_cb_args:tt)+ ] |>
        eoc => ( $($actions:tt)* )
    ) => {
        state_body!(@callback | [ [$self, $input, $ch], $($rest_cb_args)+ ] |>
            None if !$self.is_last_input() => ({
                action_list!(|$self, $input|> $($actions)* );

                return $self.break_on_end_of_input($input);
            })
        );
    };

    // NOTE: this arm is always enforced by the compiler to make match exhaustive,
    // so it's safe to break parsing loop here, since we don't have any input left
    // to parse. We execute EOF actions only if it's a last input, otherwise we just
    // break the parsing loop if it hasn't been done by the explicit EOC arm.
    ( | [ [$self:tt, $input:ident, $ch:ident ], $($rest_cb_args:tt)+ ] |>
        eof => ( $($actions:tt)* )
    ) => {
        state_body!(@callback | [ [$self, $input, $ch], $($rest_cb_args)+ ] |>
            None => ({
                if $self.is_last_input() {
                    action_list!(|$self, $input|> $($actions)* );
                }

                return $self.break_on_end_of_input($input);
            })
        );
    };

    ( | [ $scope_vars:tt, $($rest_cb_args:tt)+ ] |>
        [ $seq_pat:tt $(; $case_mod:ident)* ] => $actions:tt
    ) => {
        // NOTE: character sequence arm should be expanded in
        // place before we hit the character match block.
        ch_sequence_arm_pattern!(|$scope_vars|> $seq_pat, $actions, $($case_mod)* );
        state_body!(@callback | [ $scope_vars, $($rest_cb_args)+ ] |>);
    };

    ( | $cb_args:tt |> $pat:pat => $actions:tt ) => {
        state_body!(@callback | $cb_args |> Some($pat) => $actions);
    };
}