1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverpackage ANTLR::Runtime::BaseRecognizer;
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveruse Readonly;
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveruse Carp;
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveruse ANTLR::Runtime::RecognizerSharedState;
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveruse ANTLR::Runtime::Token;
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveruse ANTLR::Runtime::UnwantedTokenException;
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveruse ANTLR::Runtime::MissingTokenException;
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveruse ANTLR::Runtime::MismatchedTokenException;
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveruse Moose;
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
14324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverReadonly my $MEMO_RULE_FAILED => -2;
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub MEMO_RULE_FAILED { $MEMO_RULE_FAILED }
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
17324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverReadonly my $MEMO_RULE_UNKNOWN => -1;
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub MEMO_RULE_UNKNOWN { $MEMO_RULE_UNKNOWN }
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
20324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverReadonly my $INITIAL_FOLLOW_STACK_SIZE => 100;
21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub INITIAL_FOLLOW_STACK_SIZE { $INITIAL_FOLLOW_STACK_SIZE }
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# copies from Token object for convenience in actions
24324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverReadonly my $DEFAULT_TOKEN_CHANNEL => ANTLR::Runtime::Token->DEFAULT_CHANNEL;
25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub DEFAULT_TOKEN_CHANNEL { $DEFAULT_TOKEN_CHANNEL }
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
27324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverReadonly my $HIDDEN => ANTLR::Runtime::Token->HIDDEN_CHANNEL;
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub HIDDEN { $HIDDEN }
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
30324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverReadonly my $NEXT_TOKEN_RULE_NAME => 'next_token';
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub NEXT_TOKEN_RULE_NAME { $NEXT_TOKEN_RULE_NAME }
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# State of a lexer, parser, or tree parser are collected into a state
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# object so the state can be shared.  This sharing is needed to
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# have one grammar import others and share same error variables
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# and other state variables.  It's a kind of explicit multiple
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# inheritance via delegation of methods and shared state.
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverhas 'state' => (
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    is  => 'rw',
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    isa => 'ANTLR::Runtime::RecognizerSharedState',
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    default => sub { ANTLR::Runtime::RecognizerSharedState->new() },
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver);
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub reset {
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self) = @_;
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (!defined $self->state) {
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return;
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $state = $self->state;
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $state->_fsp(-1);
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $state->error_recovery(0);
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $state->last_error_index(-1);
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $state->failed(0);
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $state->syntax_errors(0);
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # wack everything related to backtracking and memoization
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $state->backtracking(0);
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # wipe cache
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $state->rule_memo([]);
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub match {
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void match(IntStream input, int ttype, BitSet follow)';
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 4;
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input, $ttype, $follow) = @_;
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $matched_symbol = $self->get_current_input_symbol($input);
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($input->LA(1) eq $ttype) {
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $input->consume();
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->state->error_recovery(0);
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->state->failed(0);
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return $matched_symbol;
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($self->state->backtracking > 0) {
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->state->failed(1);
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return $matched_symbol;
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return $self->recover_from_mismatched_token($input, $ttype, $follow);
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub match_any {
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void match_any(IntStream input)';
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 2;
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input) = @_;
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->state->error_recovery(0);
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->state->failed(0);
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $input->consume();
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub mismatch_is_unwanted_token {
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input, $ttype) = @_;
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return $input->LA(2) == $ttype;
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub mismatch_is_missing_token {
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input, $follow) = @_;
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (!defined $follow) {
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 0;
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($follow->member(ANTLR::Runtime::Token->EOR_TOKEN_TYPE)) {
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my $viable_tokens_following_this_rule = $self->compute_context_sensitive_rule_FOLLOW();
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $follow = $follow->or($viable_tokens_following_this_rule);
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ($self->state->_fsp >= 0) {
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            $follow->remove(ANTLR::Runtime::Token->EOR_TOKEN_TYPE);
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($follow->member($input->LA(1)) || $follow->member(ANTLR::Runtime::Token->EOR_TOKEN_TYPE)) {
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 1;
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return 0;
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub mismatch {
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void mismatch(IntStream input, int ttype, BitSet follow)';
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 4;
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input, $ttype, $follow) = @_;
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($self->mismatch_is_unwanted_token($input, $ttype)) {
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        ANTLR::Runtime::UnwantedTokenException->new({
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            expecting => $ttype,
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            input => $input
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        })->throw();
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    elsif ($self->mismatch_is_missing_token($input, $follow)) {
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        ANTLR::Runtime::MissingTokenException->new({
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            expecting => $ttype,
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            input => $input
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        })->throw();
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    else {
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        ANTLR::Runtime::MismatchedTokenException->new({
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            expecting => $ttype,
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            input => $input
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        })->throw();
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub report_error {
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void report_error(RecognitionException e)';
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 2;
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $e) = @_;
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($self->state->error_recovery) {
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return;
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->state->syntax_errors($self->state->syntax_errors + 1);
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->state->error_recovery(1);
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->display_recognition_error($self->get_token_names(), $e);
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return;
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub display_recognition_error {
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void display_recognition_error(String[] token_names, RecognitionException e)';
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 3;
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $token_names, $e) = @_;
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $hdr = $self->get_error_header($e);
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $msg = $self->get_error_message($e, $token_names);
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->emit_error_message("$hdr $msg");
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_error_message {
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'String get_error_message(RecognitionException e, String[] token_names)';
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 3;
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $e, $token_names) = @_;
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($e->isa('ANTLR::Runtime::MismatchedTokenException')) {
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my $token_name;
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ($e->get_expecting == ANTLR::Runtime::Token->EOF) {
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            $token_name = 'EOF';
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        } else {
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            $token_name = $token_names->[$e->get_expecting];
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 'mismatched input ' . $self->get_token_error_display($e->get_token)
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            . ' expecting ' . $token_name;
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    } elsif ($e->isa('ANTLR::Runtime::MismatchedTreeNodeException')) {
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my $token_name;
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ($e->get_expecting == ANTLR::Runtime::Token->EOF) {
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            $token_name = 'EOF';
190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        } else {
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            $token_name = $token_names->[$e->get_expecting];
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 'mismatched tree node: ' . $e->node
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            . ' expecting ' . $token_name;
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    } elsif ($e->isa('ANTLR::Runtime::NoViableAltException')) {
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 'no viable alternative at input ' . $self->get_token_error_display($e->get_token);
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    } elsif ($e->isa('ANTLR::Runtime::EarlyExitException')) {
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 'required (...)+ loop did not match anything at input '
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            . get_token_error_display($e->get_token);
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    } elsif ($e->isa('ANTLR::Runtime::MismatchedSetException')) {
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 'mismatched input ' . $self->get_token_error_display($e->get_token)
203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            . ' expecting set ' . $e->get_expecting;
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    } elsif ($e->isa('ANTLR::Runtime::MismatchedNotSetException')) {
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 'mismatched input ' . $self->get_token_error_display($e->get_token)
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            . ' expecting set ' . $e->get_expecting;
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    } elsif ($e->isa('ANTLR::Runtime::FailedPredicateException')) {
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 'rule ' . $e->rule_name . ' failed predicate: {'
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            . $e->predicate_text . '}?';
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    } else {
211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return undef;
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_number_of_syntax_errors {
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self) = @_;
217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return $self->state->syntax_errors;
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_error_header {
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'String get_error_header(RecognitionException e)';
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 2;
223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $e) = @_;
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $line = $e->get_line();
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $col = $e->get_char_position_in_line();
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return "line $line:$col";
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_token_error_display {
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'String get_token_error_display(Token t)';
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 2;
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $t) = @_;
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $s = $t->get_text();
237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (!defined $s) {
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ($t->get_type() == ANTLR::Runtime::Token->EOF) {
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            $s = '<EOF>';
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        } else {
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            my $ttype = $t->get_type();
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            $s = "<$ttype>";
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $s =~ s/\n/\\\\n/g;
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $s =~ s/\r/\\\\r/g;
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $s =~ s/\t/\\\\t/g;
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return "'$s'";
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub emit_error_message {
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void emit_error_message(String msg)';
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 2;
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $msg) = @_;
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    print STDERR $msg, "\n";
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub recover {
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void recover(IntStream input, RecognitionException re)';
263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 3;
264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input, $re) = @_;
265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($self->state->last_error_index == $input->index()) {
267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	# uh oh, another error at same token index; must be a case
268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	# where LT(1) is in the recovery token set so nothing is
269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	# consumed; consume a single token so at least to prevent
270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	# an infinite loop; this is a failsafe.
271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $input->consume();
272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->state->last_error_index($input->index());
275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $follow_set = $self->compute_error_recovery_set();
276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->begin_resync();
277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->consume_until($input, $follow_set);
278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->end_resync();
279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub begin_resync {
282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub end_resync {
285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub compute_error_recovery_set {
288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void compute_error_recovery_set()';
289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 1;
290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self) = @_;
291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->combine_follows(0);
293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub compute_context_sensitive_rule_FOLLOW {
296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void compute_context_sensitive_rule_FOLLOW()';
297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 1;
298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self) = @_;
299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->combine_follows(1);
301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub combine_follows {
304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'BitSet combine_follows(boolean exact)';
305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 2;
306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $exact) = @_;
307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $top = $self->state->_fsp;
309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $follow_set = ANTLR::Runtime::BitSet->new();
310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    foreach my $local_follow_set (reverse @{$self->state->following}) {
312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $follow_set |= $local_follow_set;
313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ($exact && $local_follow_set->member(ANTLR::Runtime::Token->EOR_TOKEN_TYPE)) {
314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            last;
315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    #$follow_set->remove(ANTLR::Runtime::Token->EOR_TOKEN_TYPE);
318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return $follow_set;
319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub recover_from_mismatched_token {
322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void recover_from_mismatched_token(IntStream input, int ttype, BitSet follow)';
323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 4;
324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input, $ttype, $follow) = @_;
325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($self->mismatch_is_unwanted_token($input, $ttype)) {
327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my $ex = ANTLR::Runtime::UnwantedTokenException->new({
328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            expecting => $ttype,
329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            input => $input
330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        });
331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->begin_resync();
333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $input->consume();
334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->end_resync();
335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->report_error($ex);
336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my $matched_symbol = $self->get_current_input_symbol($input);
338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $input->consume();
339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return $matched_symbol;
340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($self->mismatch_is_missing_token($input, $follow)) {
343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my $inserted = $self->get_missing_symbol({
344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                input => $input,
345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                expected_token_type => $ttype,
346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                follow => $follow,
347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        });
348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my $ex = ANTLR::Runtime::MissingTokenException({
349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            expecting => $ttype,
350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            input => $input,
351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            inserted => $inserted,
352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        });
353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->report_error($ex);
354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return $inserted;
355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ANTLR::Runtime::MismatchedTokenException->new({
358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        expecting => $ttype,
359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        input => $input,
360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    })->throw();
361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub recover_from_mismatched_set {
364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void recover_from_mismatched_set(IntStream input, RecognitionException e, BitSet follow)';
365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 4;
366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input, $e, $follow) = @_;
367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($self->mismatch_is_missing_token($input, $follow)) {
369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->report_error($e);
370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return $self->get_missing_symbol({
371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                input => $input,
372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                exception => $e,
373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                expected_token_type => ANTLR::Runtime::Token->INVALID_TOKEN_TYPE,
374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                follow => $follow,
375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            });
376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $e->throw();
379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub recover_from_mismatched_element {
382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'boolean recover_from_mismatched_element(IntStream input, RecognitionException e, BitSet follow)';
383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 4;
384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input, $e, $follow) = @_;
385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return 0 if (!defined $follow);
387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($follow->member(ANTLR::Runtime::Token->EOR_TOKEN_TYPE)) {
389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my $viable_tokens_following_this_rule = $self->compute_context_sensitive_rule_FOLLOW();
390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $follow |= $viable_tokens_following_this_rule;
391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $follow->remove(ANTLR::Runtime::Token->EOR_TOKEN_TYPE);
392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($follow->member($input->LA(1))) {
395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->report_error($e);
396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 1;
397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return 0;
400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_current_input_symbol {
403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input) = @_;
404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return undef;
405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_missing_symbol {
408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $arg_ref) = @_;
409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $input = $arg_ref->{input};
410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $exception = $arg_ref->{exception};
411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $expected_token_type = $arg_ref->{expected_token_type};
412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $follow = $arg_ref->{follow};
413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return undef;
415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub consume_until {
418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void consume_until(IntStream input, (int token_type | BitSet set))';
419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 3;
420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($_[2]->isa('ANTLR::Runtime::BitSet')) {
422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my ($self, $input, $set) = @_;
423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my $ttype = $input->LA(1);
425324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        while ($ttype != ANTLR::Runtime::Token->EOF && !$set->member($ttype)) {
426324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            $input->consume();
427324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            $ttype = $input->LA(1);
428324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
429324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    } else {
430324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my ($self, $input, $token_type) = @_;
431324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
432324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my $ttype = $input->LA(1);
433324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        while ($ttype != ANTLR::Runtime::Token->EOF && $ttype != $token_type) {
434324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            $input->consume();
435324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            $ttype = $input->LA(1);
436324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
437324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
438324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
439324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
440324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub push_follow {
441324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void push_follow(BitSet fset)';
442324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 2;
443324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $fset) = @_;
444324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
445324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    push @{$self->state->following}, $fset;
446324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->state->_fsp($self->state->_fsp + 1);
447324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
448324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
449324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_rule_invocation_stack {
450324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'List get_rule_invocation_stack()';
451324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 1;
452324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self) = @_;
453324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
454324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $rules = [];
455324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    for (my $i = 0; ; ++$i) {
456324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my @frame = caller $i;
457324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        last if !@frame;
458324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
459324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        my ($package, $filename, $line, $subroutine) = @frame;
460324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
461324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ($package =~ /^ANTLR::Runtime::/) {
462324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            next;
463324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
464324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
465324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ($subroutine eq NEXT_TOKEN_RULE_NAME) {
466324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            next;
467324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
468324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
469324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ($package ne ref $self) {
470324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            next;
471324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
472324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
473324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        push @{$rules}, $subroutine;
474324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
475324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
476324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
477324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_backtracking_level {
478324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'int get_backtracking_level()';
479324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 1;
480324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self) = @_;
481324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
482324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return $self->state->backtracking;
483324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
484324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
485324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub set_backtracking_level {
486324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $n) = @_;
487324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $self->state->backtracking($n);
488324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
489324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
490324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub failed {
491324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self) = @_;
492324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return $self->state->failed;
493324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
494324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
495324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_token_names {
496324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return undef;
497324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
498324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
499324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_grammar_file_name {
500324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return undef;
501324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
502324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
503324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub to_strings {
504324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'List to_strings(List tokens)';
505324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 2;
506324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $tokens) = @_;
507324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
508324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (!defined $tokens) {
509324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return undef;
510324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
511324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
512324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return map { $_->get_text() } @{$tokens};
513324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
514324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
515324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_rule_memoization {
516324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'int get_rule_memoization(int rule_index, int rule_start_index)';
517324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 3;
518324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $rule_index, $rule_start_index) = @_;
519324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
520324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (!defined $self->rule_memo->[$rule_index]) {
521324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->rule_memo->[$rule_index] = {};
522324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
523324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
524324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $stop_index = $self->state->rule_memo->[$rule_index]->{$rule_start_index};
525324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (!defined $stop_index) {
526324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return $self->MEMO_RULE_UNKNOWN;
527324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
528324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return $stop_index;
529324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
530324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
531324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub alredy_parsed_rule {
532324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'boolean alredy_parsed_rule(IntStream input, int rule_index)';
533324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 3;
534324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input, $rule_index) = @_;
535324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
536324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $stop_index = $self->get_rule_memoization($rule_index, $input->index());
537324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($stop_index == $self->MEMO_RULE_UNKNOWN) {
538324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 0;
539324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
540324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
541324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($stop_index == $self->MEMO_RULE_FAILED) {
542324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->state->failed(1);
543324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    } else {
544324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $input->seek($stop_index + 1);
545324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
546324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return 1;
547324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
548324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
549324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub memoize {
550324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void memoize(IntStream input, int rule_index, int rule_start_index)';
551324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 4;
552324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $input, $rule_index, $rule_start_index) = @_;
553324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
554324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $stop_token_index = $self->state->failed ? $self->MEMO_RULE_FAILED : $input->index() - 1;
555324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (defined $self->state->rule_memo->[$rule_index]) {
556324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $self->state->rule_memo->[$rule_index]->{$rule_start_index} = $stop_token_index;
557324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
558324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
559324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
560324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub get_rule_memoization_cache_size {
561324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'int get_rule_memoization_cache_size()';
562324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 1;
563324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self) = @_;
564324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
565324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my $n = 0;
566324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    foreach my $m (@{$self->state->rule_memo}) {
567324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        $n += keys %{$m} if defined $m;
568324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
569324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
570324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return $n;
571324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
572324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
573324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub trace_in {
574324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void trace_in(String rule_name, int rule_index, input_symbol)';
575324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 4;
576324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $rule_name, $rule_index, $input_symbol) = @_;
577324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
578324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    print "enter $rule_name $input_symbol";
579324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($self->state->failed) {
580324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        print ' failed=', $self->state->failed;
581324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
582324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($self->state->backtracking > 0) {
583324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        print ' backtracking=', $self->state->backtracking;
584324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
585324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    print "\n";
586324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
587324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
588324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversub trace_out {
589324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Readonly my $usage => 'void trace_out(String rule_name, int rule_index, input_symbol)';
590324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    croak $usage if @_ != 4;
591324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    my ($self, $rule_name, $rule_index, $input_symbol) = @_;
592324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
593324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    print "exit $rule_name $input_symbol";
594324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($self->state->failed) {
595324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        print ' failed=', $self->state->failed;
596324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
597324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if ($self->state->backtracking > 0) {
598324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        print ' backtracking=', $self->state->backtracking;
599324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
600324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    print "\n";
601324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
602324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
603324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverno Moose;
604324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver__PACKAGE__->meta->make_immutable();
605324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver1;
606324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver__END__
607324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
608324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=head1 NAME
609324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
610324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverANTLR::Runtime::BaseRecognizer
611324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
612324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=head1 DESCRIPTION
613324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
614324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverA generic recognizer that can handle recognizers generated from
615324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverlexer, parser, and tree grammars.  This is all the parsing
616324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruversupport code essentially; most of it is error recovery stuff and
617324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverbacktracking.
618