xref: /aosp_15_r20/external/antlr/runtime/Python/antlr3/exceptions.py (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1*16467b97STreehugger Robot"""ANTLR3 exception hierarchy"""
2*16467b97STreehugger Robot
3*16467b97STreehugger Robot# begin[licence]
4*16467b97STreehugger Robot#
5*16467b97STreehugger Robot# [The "BSD licence"]
6*16467b97STreehugger Robot# Copyright (c) 2005-2008 Terence Parr
7*16467b97STreehugger Robot# All rights reserved.
8*16467b97STreehugger Robot#
9*16467b97STreehugger Robot# Redistribution and use in source and binary forms, with or without
10*16467b97STreehugger Robot# modification, are permitted provided that the following conditions
11*16467b97STreehugger Robot# are met:
12*16467b97STreehugger Robot# 1. Redistributions of source code must retain the above copyright
13*16467b97STreehugger Robot#    notice, this list of conditions and the following disclaimer.
14*16467b97STreehugger Robot# 2. Redistributions in binary form must reproduce the above copyright
15*16467b97STreehugger Robot#    notice, this list of conditions and the following disclaimer in the
16*16467b97STreehugger Robot#    documentation and/or other materials provided with the distribution.
17*16467b97STreehugger Robot# 3. The name of the author may not be used to endorse or promote products
18*16467b97STreehugger Robot#    derived from this software without specific prior written permission.
19*16467b97STreehugger Robot#
20*16467b97STreehugger Robot# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21*16467b97STreehugger Robot# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22*16467b97STreehugger Robot# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23*16467b97STreehugger Robot# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24*16467b97STreehugger Robot# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25*16467b97STreehugger Robot# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26*16467b97STreehugger Robot# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27*16467b97STreehugger Robot# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28*16467b97STreehugger Robot# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29*16467b97STreehugger Robot# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*16467b97STreehugger Robot#
31*16467b97STreehugger Robot# end[licence]
32*16467b97STreehugger Robot
33*16467b97STreehugger Robotfrom antlr3.constants import INVALID_TOKEN_TYPE
34*16467b97STreehugger Robot
35*16467b97STreehugger Robot
36*16467b97STreehugger Robotclass BacktrackingFailed(Exception):
37*16467b97STreehugger Robot    """@brief Raised to signal failed backtrack attempt"""
38*16467b97STreehugger Robot
39*16467b97STreehugger Robot    pass
40*16467b97STreehugger Robot
41*16467b97STreehugger Robot
42*16467b97STreehugger Robotclass RecognitionException(Exception):
43*16467b97STreehugger Robot    """@brief The root of the ANTLR exception hierarchy.
44*16467b97STreehugger Robot
45*16467b97STreehugger Robot    To avoid English-only error messages and to generally make things
46*16467b97STreehugger Robot    as flexible as possible, these exceptions are not created with strings,
47*16467b97STreehugger Robot    but rather the information necessary to generate an error.  Then
48*16467b97STreehugger Robot    the various reporting methods in Parser and Lexer can be overridden
49*16467b97STreehugger Robot    to generate a localized error message.  For example, MismatchedToken
50*16467b97STreehugger Robot    exceptions are built with the expected token type.
51*16467b97STreehugger Robot    So, don't expect getMessage() to return anything.
52*16467b97STreehugger Robot
53*16467b97STreehugger Robot    Note that as of Java 1.4, you can access the stack trace, which means
54*16467b97STreehugger Robot    that you can compute the complete trace of rules from the start symbol.
55*16467b97STreehugger Robot    This gives you considerable context information with which to generate
56*16467b97STreehugger Robot    useful error messages.
57*16467b97STreehugger Robot
58*16467b97STreehugger Robot    ANTLR generates code that throws exceptions upon recognition error and
59*16467b97STreehugger Robot    also generates code to catch these exceptions in each rule.  If you
60*16467b97STreehugger Robot    want to quit upon first error, you can turn off the automatic error
61*16467b97STreehugger Robot    handling mechanism using rulecatch action, but you still need to
62*16467b97STreehugger Robot    override methods mismatch and recoverFromMismatchSet.
63*16467b97STreehugger Robot
64*16467b97STreehugger Robot    In general, the recognition exceptions can track where in a grammar a
65*16467b97STreehugger Robot    problem occurred and/or what was the expected input.  While the parser
66*16467b97STreehugger Robot    knows its state (such as current input symbol and line info) that
67*16467b97STreehugger Robot    state can change before the exception is reported so current token index
68*16467b97STreehugger Robot    is computed and stored at exception time.  From this info, you can
69*16467b97STreehugger Robot    perhaps print an entire line of input not just a single token, for example.
70*16467b97STreehugger Robot    Better to just say the recognizer had a problem and then let the parser
71*16467b97STreehugger Robot    figure out a fancy report.
72*16467b97STreehugger Robot
73*16467b97STreehugger Robot    """
74*16467b97STreehugger Robot
75*16467b97STreehugger Robot    def __init__(self, input=None):
76*16467b97STreehugger Robot        Exception.__init__(self)
77*16467b97STreehugger Robot
78*16467b97STreehugger Robot	# What input stream did the error occur in?
79*16467b97STreehugger Robot        self.input = None
80*16467b97STreehugger Robot
81*16467b97STreehugger Robot        # What is index of token/char were we looking at when the error
82*16467b97STreehugger Robot        # occurred?
83*16467b97STreehugger Robot        self.index = None
84*16467b97STreehugger Robot
85*16467b97STreehugger Robot	# The current Token when an error occurred.  Since not all streams
86*16467b97STreehugger Robot	# can retrieve the ith Token, we have to track the Token object.
87*16467b97STreehugger Robot	# For parsers.  Even when it's a tree parser, token might be set.
88*16467b97STreehugger Robot        self.token = None
89*16467b97STreehugger Robot
90*16467b97STreehugger Robot	# If this is a tree parser exception, node is set to the node with
91*16467b97STreehugger Robot	# the problem.
92*16467b97STreehugger Robot        self.node = None
93*16467b97STreehugger Robot
94*16467b97STreehugger Robot	# The current char when an error occurred. For lexers.
95*16467b97STreehugger Robot        self.c = None
96*16467b97STreehugger Robot
97*16467b97STreehugger Robot	# Track the line at which the error occurred in case this is
98*16467b97STreehugger Robot	# generated from a lexer.  We need to track this since the
99*16467b97STreehugger Robot        # unexpected char doesn't carry the line info.
100*16467b97STreehugger Robot        self.line = None
101*16467b97STreehugger Robot
102*16467b97STreehugger Robot        self.charPositionInLine = None
103*16467b97STreehugger Robot
104*16467b97STreehugger Robot        # If you are parsing a tree node stream, you will encounter som
105*16467b97STreehugger Robot        # imaginary nodes w/o line/col info.  We now search backwards looking
106*16467b97STreehugger Robot        # for most recent token with line/col info, but notify getErrorHeader()
107*16467b97STreehugger Robot        # that info is approximate.
108*16467b97STreehugger Robot        self.approximateLineInfo = False
109*16467b97STreehugger Robot
110*16467b97STreehugger Robot
111*16467b97STreehugger Robot        if input is not None:
112*16467b97STreehugger Robot            self.input = input
113*16467b97STreehugger Robot            self.index = input.index()
114*16467b97STreehugger Robot
115*16467b97STreehugger Robot            # late import to avoid cyclic dependencies
116*16467b97STreehugger Robot            from antlr3.streams import TokenStream, CharStream
117*16467b97STreehugger Robot            from antlr3.tree import TreeNodeStream
118*16467b97STreehugger Robot
119*16467b97STreehugger Robot            if isinstance(self.input, TokenStream):
120*16467b97STreehugger Robot                self.token = self.input.LT(1)
121*16467b97STreehugger Robot                self.line = self.token.line
122*16467b97STreehugger Robot                self.charPositionInLine = self.token.charPositionInLine
123*16467b97STreehugger Robot
124*16467b97STreehugger Robot            if isinstance(self.input, TreeNodeStream):
125*16467b97STreehugger Robot                self.extractInformationFromTreeNodeStream(self.input)
126*16467b97STreehugger Robot
127*16467b97STreehugger Robot            else:
128*16467b97STreehugger Robot                if isinstance(self.input, CharStream):
129*16467b97STreehugger Robot                    self.c = self.input.LT(1)
130*16467b97STreehugger Robot                    self.line = self.input.line
131*16467b97STreehugger Robot                    self.charPositionInLine = self.input.charPositionInLine
132*16467b97STreehugger Robot
133*16467b97STreehugger Robot                else:
134*16467b97STreehugger Robot                    self.c = self.input.LA(1)
135*16467b97STreehugger Robot
136*16467b97STreehugger Robot    def extractInformationFromTreeNodeStream(self, nodes):
137*16467b97STreehugger Robot        from antlr3.tree import Tree, CommonTree
138*16467b97STreehugger Robot        from antlr3.tokens import CommonToken
139*16467b97STreehugger Robot
140*16467b97STreehugger Robot        self.node = nodes.LT(1)
141*16467b97STreehugger Robot        adaptor = nodes.adaptor
142*16467b97STreehugger Robot        payload = adaptor.getToken(self.node)
143*16467b97STreehugger Robot        if payload is not None:
144*16467b97STreehugger Robot            self.token = payload
145*16467b97STreehugger Robot            if payload.line <= 0:
146*16467b97STreehugger Robot                # imaginary node; no line/pos info; scan backwards
147*16467b97STreehugger Robot                i = -1
148*16467b97STreehugger Robot                priorNode = nodes.LT(i)
149*16467b97STreehugger Robot                while priorNode is not None:
150*16467b97STreehugger Robot                    priorPayload = adaptor.getToken(priorNode)
151*16467b97STreehugger Robot                    if priorPayload is not None and priorPayload.line > 0:
152*16467b97STreehugger Robot                        # we found the most recent real line / pos info
153*16467b97STreehugger Robot                        self.line = priorPayload.line
154*16467b97STreehugger Robot                        self.charPositionInLine = priorPayload.charPositionInLine
155*16467b97STreehugger Robot                        self.approximateLineInfo = True
156*16467b97STreehugger Robot                        break
157*16467b97STreehugger Robot
158*16467b97STreehugger Robot                    i -= 1
159*16467b97STreehugger Robot                    priorNode = nodes.LT(i)
160*16467b97STreehugger Robot
161*16467b97STreehugger Robot            else: # node created from real token
162*16467b97STreehugger Robot                self.line = payload.line
163*16467b97STreehugger Robot                self.charPositionInLine = payload.charPositionInLine
164*16467b97STreehugger Robot
165*16467b97STreehugger Robot        elif isinstance(self.node, Tree):
166*16467b97STreehugger Robot            self.line = self.node.line
167*16467b97STreehugger Robot            self.charPositionInLine = self.node.charPositionInLine
168*16467b97STreehugger Robot            if isinstance(self.node, CommonTree):
169*16467b97STreehugger Robot                self.token = self.node.token
170*16467b97STreehugger Robot
171*16467b97STreehugger Robot        else:
172*16467b97STreehugger Robot            type = adaptor.getType(self.node)
173*16467b97STreehugger Robot            text = adaptor.getText(self.node)
174*16467b97STreehugger Robot            self.token = CommonToken(type=type, text=text)
175*16467b97STreehugger Robot
176*16467b97STreehugger Robot
177*16467b97STreehugger Robot    def getUnexpectedType(self):
178*16467b97STreehugger Robot        """Return the token type or char of the unexpected input element"""
179*16467b97STreehugger Robot
180*16467b97STreehugger Robot        from antlr3.streams import TokenStream
181*16467b97STreehugger Robot        from antlr3.tree import TreeNodeStream
182*16467b97STreehugger Robot
183*16467b97STreehugger Robot        if isinstance(self.input, TokenStream):
184*16467b97STreehugger Robot            return self.token.type
185*16467b97STreehugger Robot
186*16467b97STreehugger Robot        elif isinstance(self.input, TreeNodeStream):
187*16467b97STreehugger Robot            adaptor = self.input.treeAdaptor
188*16467b97STreehugger Robot            return adaptor.getType(self.node)
189*16467b97STreehugger Robot
190*16467b97STreehugger Robot        else:
191*16467b97STreehugger Robot            return self.c
192*16467b97STreehugger Robot
193*16467b97STreehugger Robot    unexpectedType = property(getUnexpectedType)
194*16467b97STreehugger Robot
195*16467b97STreehugger Robot
196*16467b97STreehugger Robotclass MismatchedTokenException(RecognitionException):
197*16467b97STreehugger Robot    """@brief A mismatched char or Token or tree node."""
198*16467b97STreehugger Robot
199*16467b97STreehugger Robot    def __init__(self, expecting, input):
200*16467b97STreehugger Robot        RecognitionException.__init__(self, input)
201*16467b97STreehugger Robot        self.expecting = expecting
202*16467b97STreehugger Robot
203*16467b97STreehugger Robot
204*16467b97STreehugger Robot    def __str__(self):
205*16467b97STreehugger Robot        #return "MismatchedTokenException("+self.expecting+")"
206*16467b97STreehugger Robot        return "MismatchedTokenException(%r!=%r)" % (
207*16467b97STreehugger Robot            self.getUnexpectedType(), self.expecting
208*16467b97STreehugger Robot            )
209*16467b97STreehugger Robot    __repr__ = __str__
210*16467b97STreehugger Robot
211*16467b97STreehugger Robot
212*16467b97STreehugger Robotclass UnwantedTokenException(MismatchedTokenException):
213*16467b97STreehugger Robot    """An extra token while parsing a TokenStream"""
214*16467b97STreehugger Robot
215*16467b97STreehugger Robot    def getUnexpectedToken(self):
216*16467b97STreehugger Robot        return self.token
217*16467b97STreehugger Robot
218*16467b97STreehugger Robot
219*16467b97STreehugger Robot    def __str__(self):
220*16467b97STreehugger Robot        exp = ", expected %s" % self.expecting
221*16467b97STreehugger Robot        if self.expecting == INVALID_TOKEN_TYPE:
222*16467b97STreehugger Robot            exp = ""
223*16467b97STreehugger Robot
224*16467b97STreehugger Robot        if self.token is None:
225*16467b97STreehugger Robot            return "UnwantedTokenException(found=%s%s)" % (None, exp)
226*16467b97STreehugger Robot
227*16467b97STreehugger Robot        return "UnwantedTokenException(found=%s%s)" % (self.token.text, exp)
228*16467b97STreehugger Robot    __repr__ = __str__
229*16467b97STreehugger Robot
230*16467b97STreehugger Robot
231*16467b97STreehugger Robotclass MissingTokenException(MismatchedTokenException):
232*16467b97STreehugger Robot    """
233*16467b97STreehugger Robot    We were expecting a token but it's not found.  The current token
234*16467b97STreehugger Robot    is actually what we wanted next.
235*16467b97STreehugger Robot    """
236*16467b97STreehugger Robot
237*16467b97STreehugger Robot    def __init__(self, expecting, input, inserted):
238*16467b97STreehugger Robot        MismatchedTokenException.__init__(self, expecting, input)
239*16467b97STreehugger Robot
240*16467b97STreehugger Robot        self.inserted = inserted
241*16467b97STreehugger Robot
242*16467b97STreehugger Robot
243*16467b97STreehugger Robot    def getMissingType(self):
244*16467b97STreehugger Robot        return self.expecting
245*16467b97STreehugger Robot
246*16467b97STreehugger Robot
247*16467b97STreehugger Robot    def __str__(self):
248*16467b97STreehugger Robot        if self.inserted is not None and self.token is not None:
249*16467b97STreehugger Robot            return "MissingTokenException(inserted %r at %r)" % (
250*16467b97STreehugger Robot                self.inserted, self.token.text)
251*16467b97STreehugger Robot
252*16467b97STreehugger Robot        if self.token is not None:
253*16467b97STreehugger Robot            return "MissingTokenException(at %r)" % self.token.text
254*16467b97STreehugger Robot
255*16467b97STreehugger Robot        return "MissingTokenException"
256*16467b97STreehugger Robot    __repr__ = __str__
257*16467b97STreehugger Robot
258*16467b97STreehugger Robot
259*16467b97STreehugger Robotclass MismatchedRangeException(RecognitionException):
260*16467b97STreehugger Robot    """@brief The next token does not match a range of expected types."""
261*16467b97STreehugger Robot
262*16467b97STreehugger Robot    def __init__(self, a, b, input):
263*16467b97STreehugger Robot        RecognitionException.__init__(self, input)
264*16467b97STreehugger Robot
265*16467b97STreehugger Robot        self.a = a
266*16467b97STreehugger Robot        self.b = b
267*16467b97STreehugger Robot
268*16467b97STreehugger Robot
269*16467b97STreehugger Robot    def __str__(self):
270*16467b97STreehugger Robot        return "MismatchedRangeException(%r not in [%r..%r])" % (
271*16467b97STreehugger Robot            self.getUnexpectedType(), self.a, self.b
272*16467b97STreehugger Robot            )
273*16467b97STreehugger Robot    __repr__ = __str__
274*16467b97STreehugger Robot
275*16467b97STreehugger Robot
276*16467b97STreehugger Robotclass MismatchedSetException(RecognitionException):
277*16467b97STreehugger Robot    """@brief The next token does not match a set of expected types."""
278*16467b97STreehugger Robot
279*16467b97STreehugger Robot    def __init__(self, expecting, input):
280*16467b97STreehugger Robot        RecognitionException.__init__(self, input)
281*16467b97STreehugger Robot
282*16467b97STreehugger Robot        self.expecting = expecting
283*16467b97STreehugger Robot
284*16467b97STreehugger Robot
285*16467b97STreehugger Robot    def __str__(self):
286*16467b97STreehugger Robot        return "MismatchedSetException(%r not in %r)" % (
287*16467b97STreehugger Robot            self.getUnexpectedType(), self.expecting
288*16467b97STreehugger Robot            )
289*16467b97STreehugger Robot    __repr__ = __str__
290*16467b97STreehugger Robot
291*16467b97STreehugger Robot
292*16467b97STreehugger Robotclass MismatchedNotSetException(MismatchedSetException):
293*16467b97STreehugger Robot    """@brief Used for remote debugger deserialization"""
294*16467b97STreehugger Robot
295*16467b97STreehugger Robot    def __str__(self):
296*16467b97STreehugger Robot        return "MismatchedNotSetException(%r!=%r)" % (
297*16467b97STreehugger Robot            self.getUnexpectedType(), self.expecting
298*16467b97STreehugger Robot            )
299*16467b97STreehugger Robot    __repr__ = __str__
300*16467b97STreehugger Robot
301*16467b97STreehugger Robot
302*16467b97STreehugger Robotclass NoViableAltException(RecognitionException):
303*16467b97STreehugger Robot    """@brief Unable to decide which alternative to choose."""
304*16467b97STreehugger Robot
305*16467b97STreehugger Robot    def __init__(
306*16467b97STreehugger Robot        self, grammarDecisionDescription, decisionNumber, stateNumber, input
307*16467b97STreehugger Robot        ):
308*16467b97STreehugger Robot        RecognitionException.__init__(self, input)
309*16467b97STreehugger Robot
310*16467b97STreehugger Robot        self.grammarDecisionDescription = grammarDecisionDescription
311*16467b97STreehugger Robot        self.decisionNumber = decisionNumber
312*16467b97STreehugger Robot        self.stateNumber = stateNumber
313*16467b97STreehugger Robot
314*16467b97STreehugger Robot
315*16467b97STreehugger Robot    def __str__(self):
316*16467b97STreehugger Robot        return "NoViableAltException(%r!=[%r])" % (
317*16467b97STreehugger Robot            self.unexpectedType, self.grammarDecisionDescription
318*16467b97STreehugger Robot            )
319*16467b97STreehugger Robot    __repr__ = __str__
320*16467b97STreehugger Robot
321*16467b97STreehugger Robot
322*16467b97STreehugger Robotclass EarlyExitException(RecognitionException):
323*16467b97STreehugger Robot    """@brief The recognizer did not match anything for a (..)+ loop."""
324*16467b97STreehugger Robot
325*16467b97STreehugger Robot    def __init__(self, decisionNumber, input):
326*16467b97STreehugger Robot        RecognitionException.__init__(self, input)
327*16467b97STreehugger Robot
328*16467b97STreehugger Robot        self.decisionNumber = decisionNumber
329*16467b97STreehugger Robot
330*16467b97STreehugger Robot
331*16467b97STreehugger Robotclass FailedPredicateException(RecognitionException):
332*16467b97STreehugger Robot    """@brief A semantic predicate failed during validation.
333*16467b97STreehugger Robot
334*16467b97STreehugger Robot    Validation of predicates
335*16467b97STreehugger Robot    occurs when normally parsing the alternative just like matching a token.
336*16467b97STreehugger Robot    Disambiguating predicate evaluation occurs when we hoist a predicate into
337*16467b97STreehugger Robot    a prediction decision.
338*16467b97STreehugger Robot    """
339*16467b97STreehugger Robot
340*16467b97STreehugger Robot    def __init__(self, input, ruleName, predicateText):
341*16467b97STreehugger Robot        RecognitionException.__init__(self, input)
342*16467b97STreehugger Robot
343*16467b97STreehugger Robot        self.ruleName = ruleName
344*16467b97STreehugger Robot        self.predicateText = predicateText
345*16467b97STreehugger Robot
346*16467b97STreehugger Robot
347*16467b97STreehugger Robot    def __str__(self):
348*16467b97STreehugger Robot        return "FailedPredicateException("+self.ruleName+",{"+self.predicateText+"}?)"
349*16467b97STreehugger Robot    __repr__ = __str__
350*16467b97STreehugger Robot
351*16467b97STreehugger Robot
352*16467b97STreehugger Robotclass MismatchedTreeNodeException(RecognitionException):
353*16467b97STreehugger Robot    """@brief The next tree mode does not match the expected type."""
354*16467b97STreehugger Robot
355*16467b97STreehugger Robot    def __init__(self, expecting, input):
356*16467b97STreehugger Robot        RecognitionException.__init__(self, input)
357*16467b97STreehugger Robot
358*16467b97STreehugger Robot        self.expecting = expecting
359*16467b97STreehugger Robot
360*16467b97STreehugger Robot    def __str__(self):
361*16467b97STreehugger Robot        return "MismatchedTreeNodeException(%r!=%r)" % (
362*16467b97STreehugger Robot            self.getUnexpectedType(), self.expecting
363*16467b97STreehugger Robot            )
364*16467b97STreehugger Robot    __repr__ = __str__
365