exceptions.py
Go to the documentation of this file.
00001 """ANTLR3 exception hierarchy"""
00002 
00003 # begin[licence]
00004 #
00005 # [The "BSD licence"]
00006 # Copyright (c) 2005-2008 Terence Parr
00007 # All rights reserved.
00008 #
00009 # Redistribution and use in source and binary forms, with or without
00010 # modification, are permitted provided that the following conditions
00011 # are met:
00012 # 1. Redistributions of source code must retain the above copyright
00013 #    notice, this list of conditions and the following disclaimer.
00014 # 2. Redistributions in binary form must reproduce the above copyright
00015 #    notice, this list of conditions and the following disclaimer in the
00016 #    documentation and/or other materials provided with the distribution.
00017 # 3. The name of the author may not be used to endorse or promote products
00018 #    derived from this software without specific prior written permission.
00019 #
00020 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00021 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00022 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00023 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00024 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00025 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00026 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00027 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00029 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 #
00031 # end[licence]
00032 
00033 from constants import INVALID_TOKEN_TYPE
00034 
00035 
00036 class BacktrackingFailed(Exception):
00037     """@brief Raised to signal failed backtrack attempt"""
00038 
00039     pass
00040 
00041 
00042 class RecognitionException(Exception):
00043     """@brief The root of the ANTLR exception hierarchy.
00044 
00045     To avoid English-only error messages and to generally make things
00046     as flexible as possible, these exceptions are not created with strings,
00047     but rather the information necessary to generate an error.  Then
00048     the various reporting methods in Parser and Lexer can be overridden
00049     to generate a localized error message.  For example, MismatchedToken
00050     exceptions are built with the expected token type.
00051     So, don't expect getMessage() to return anything.
00052 
00053     Note that as of Java 1.4, you can access the stack trace, which means
00054     that you can compute the complete trace of rules from the start symbol.
00055     This gives you considerable context information with which to generate
00056     useful error messages.
00057 
00058     ANTLR generates code that throws exceptions upon recognition error and
00059     also generates code to catch these exceptions in each rule.  If you
00060     want to quit upon first error, you can turn off the automatic error
00061     handling mechanism using rulecatch action, but you still need to
00062     override methods mismatch and recoverFromMismatchSet.
00063     
00064     In general, the recognition exceptions can track where in a grammar a
00065     problem occurred and/or what was the expected input.  While the parser
00066     knows its state (such as current input symbol and line info) that
00067     state can change before the exception is reported so current token index
00068     is computed and stored at exception time.  From this info, you can
00069     perhaps print an entire line of input not just a single token, for example.
00070     Better to just say the recognizer had a problem and then let the parser
00071     figure out a fancy report.
00072     
00073     """
00074 
00075     def __init__(self, input=None):
00076         Exception.__init__(self)
00077 
00078         # What input stream did the error occur in?
00079         self.input = None
00080 
00081         # What is index of token/char were we looking at when the error
00082         # occurred?
00083         self.index = None
00084 
00085         # The current Token when an error occurred.  Since not all streams
00086         # can retrieve the ith Token, we have to track the Token object.
00087         # For parsers.  Even when it's a tree parser, token might be set.
00088         self.token = None
00089 
00090         # If this is a tree parser exception, node is set to the node with
00091         # the problem.
00092         self.node = None
00093 
00094         # The current char when an error occurred. For lexers.
00095         self.c = None
00096 
00097         # Track the line at which the error occurred in case this is
00098         # generated from a lexer.  We need to track this since the
00099         # unexpected char doesn't carry the line info.
00100         self.line = None
00101 
00102         self.charPositionInLine = None
00103 
00104         # If you are parsing a tree node stream, you will encounter som
00105         # imaginary nodes w/o line/col info.  We now search backwards looking
00106         # for most recent token with line/col info, but notify getErrorHeader()
00107         # that info is approximate.
00108         self.approximateLineInfo = False
00109 
00110         
00111         if input is not None:
00112             self.input = input
00113             self.index = input.index()
00114 
00115             # late import to avoid cyclic dependencies
00116             from streams import TokenStream, CharStream
00117             from tree import TreeNodeStream
00118 
00119             if isinstance(self.input, TokenStream):
00120                 self.token = self.input.LT(1)
00121                 self.line = self.token.line
00122                 self.charPositionInLine = self.token.charPositionInLine
00123 
00124             if isinstance(self.input, TreeNodeStream):
00125                 self.extractInformationFromTreeNodeStream(self.input)
00126 
00127             else:
00128                 if isinstance(self.input, CharStream):
00129                     self.c = self.input.LT(1)
00130                     self.line = self.input.line
00131                     self.charPositionInLine = self.input.charPositionInLine
00132 
00133                 else:
00134                     self.c = self.input.LA(1)
00135 
00136     def extractInformationFromTreeNodeStream(self, nodes):
00137         from tree import Tree, CommonTree
00138         from tokens import CommonToken
00139         
00140         self.node = nodes.LT(1)
00141         adaptor = nodes.adaptor
00142         payload = adaptor.getToken(self.node)
00143         if payload is not None:
00144             self.token = payload
00145             if payload.line <= 0:
00146                 # imaginary node; no line/pos info; scan backwards
00147                 i = -1
00148                 priorNode = nodes.LT(i)
00149                 while priorNode is not None:
00150                     priorPayload = adaptor.getToken(priorNode)
00151                     if priorPayload is not None and priorPayload.line > 0:
00152                         # we found the most recent real line / pos info
00153                         self.line = priorPayload.line
00154                         self.charPositionInLine = priorPayload.charPositionInLine
00155                         self.approximateLineInfo = True
00156                         break
00157                     
00158                     i -= 1
00159                     priorNode = nodes.LT(i)
00160                     
00161             else: # node created from real token
00162                 self.line = payload.line
00163                 self.charPositionInLine = payload.charPositionInLine
00164                 
00165         elif isinstance(self.node, Tree):
00166             self.line = self.node.line
00167             self.charPositionInLine = self.node.charPositionInLine
00168             if isinstance(self.node, CommonTree):
00169                 self.token = self.node.token
00170 
00171         else:
00172             type = adaptor.getType(self.node)
00173             text = adaptor.getText(self.node)
00174             self.token = CommonToken(type=type, text=text)
00175 
00176      
00177     def getUnexpectedType(self):
00178         """Return the token type or char of the unexpected input element"""
00179 
00180         from streams import TokenStream
00181         from tree import TreeNodeStream
00182 
00183         if isinstance(self.input, TokenStream):
00184             return self.token.type
00185 
00186         elif isinstance(self.input, TreeNodeStream):
00187             adaptor = self.input.treeAdaptor
00188             return adaptor.getType(self.node)
00189 
00190         else:
00191             return self.c
00192 
00193     unexpectedType = property(getUnexpectedType)
00194     
00195 
00196 class MismatchedTokenException(RecognitionException):
00197     """@brief A mismatched char or Token or tree node."""
00198     
00199     def __init__(self, expecting, input):
00200         RecognitionException.__init__(self, input)
00201         self.expecting = expecting
00202         
00203 
00204     def __str__(self):
00205         #return "MismatchedTokenException("+self.expecting+")"
00206         return "MismatchedTokenException(%r!=%r)" % (
00207             self.getUnexpectedType(), self.expecting
00208             )
00209     __repr__ = __str__
00210 
00211 
00212 class UnwantedTokenException(MismatchedTokenException):
00213     """An extra token while parsing a TokenStream"""
00214 
00215     def getUnexpectedToken(self):
00216         return self.token
00217 
00218 
00219     def __str__(self):
00220         exp = ", expected %s" % self.expecting
00221         if self.expecting == INVALID_TOKEN_TYPE:
00222             exp = ""
00223 
00224         if self.token is None:
00225             return "UnwantedTokenException(found=%s%s)" % (None, exp)
00226 
00227         return "UnwantedTokenException(found=%s%s)" % (self.token.text, exp)
00228     __repr__ = __str__
00229 
00230 
00231 class MissingTokenException(MismatchedTokenException):
00232     """
00233     We were expecting a token but it's not found.  The current token
00234     is actually what we wanted next.
00235     """
00236 
00237     def __init__(self, expecting, input, inserted):
00238         MismatchedTokenException.__init__(self, expecting, input)
00239 
00240         self.inserted = inserted
00241 
00242 
00243     def getMissingType(self):
00244         return self.expecting
00245 
00246 
00247     def __str__(self):
00248         if self.inserted is not None and self.token is not None:
00249             return "MissingTokenException(inserted %r at %r)" % (
00250                 self.inserted, self.token.text)
00251 
00252         if self.token is not None:
00253             return "MissingTokenException(at %r)" % self.token.text
00254 
00255         return "MissingTokenException"
00256     __repr__ = __str__
00257 
00258 
00259 class MismatchedRangeException(RecognitionException):
00260     """@brief The next token does not match a range of expected types."""
00261 
00262     def __init__(self, a, b, input):
00263         RecognitionException.__init__(self, input)
00264 
00265         self.a = a
00266         self.b = b
00267         
00268 
00269     def __str__(self):
00270         return "MismatchedRangeException(%r not in [%r..%r])" % (
00271             self.getUnexpectedType(), self.a, self.b
00272             )
00273     __repr__ = __str__
00274     
00275 
00276 class MismatchedSetException(RecognitionException):
00277     """@brief The next token does not match a set of expected types."""
00278 
00279     def __init__(self, expecting, input):
00280         RecognitionException.__init__(self, input)
00281 
00282         self.expecting = expecting
00283         
00284 
00285     def __str__(self):
00286         return "MismatchedSetException(%r not in %r)" % (
00287             self.getUnexpectedType(), self.expecting
00288             )
00289     __repr__ = __str__
00290 
00291 
00292 class MismatchedNotSetException(MismatchedSetException):
00293     """@brief Used for remote debugger deserialization"""
00294     
00295     def __str__(self):
00296         return "MismatchedNotSetException(%r!=%r)" % (
00297             self.getUnexpectedType(), self.expecting
00298             )
00299     __repr__ = __str__
00300 
00301 
00302 class NoViableAltException(RecognitionException):
00303     """@brief Unable to decide which alternative to choose."""
00304 
00305     def __init__(
00306         self, grammarDecisionDescription, decisionNumber, stateNumber, input
00307         ):
00308         RecognitionException.__init__(self, input)
00309 
00310         self.grammarDecisionDescription = grammarDecisionDescription
00311         self.decisionNumber = decisionNumber
00312         self.stateNumber = stateNumber
00313 
00314 
00315     def __str__(self):
00316         return "NoViableAltException(%r!=[%r])" % (
00317             self.unexpectedType, self.grammarDecisionDescription
00318             )
00319     __repr__ = __str__
00320     
00321 
00322 class EarlyExitException(RecognitionException):
00323     """@brief The recognizer did not match anything for a (..)+ loop."""
00324 
00325     def __init__(self, decisionNumber, input):
00326         RecognitionException.__init__(self, input)
00327 
00328         self.decisionNumber = decisionNumber
00329 
00330 
00331 class FailedPredicateException(RecognitionException):
00332     """@brief A semantic predicate failed during validation.
00333 
00334     Validation of predicates
00335     occurs when normally parsing the alternative just like matching a token.
00336     Disambiguating predicate evaluation occurs when we hoist a predicate into
00337     a prediction decision.
00338     """
00339 
00340     def __init__(self, input, ruleName, predicateText):
00341         RecognitionException.__init__(self, input)
00342         
00343         self.ruleName = ruleName
00344         self.predicateText = predicateText
00345 
00346 
00347     def __str__(self):
00348         return "FailedPredicateException("+self.ruleName+",{"+self.predicateText+"}?)"
00349     __repr__ = __str__
00350     
00351 
00352 class MismatchedTreeNodeException(RecognitionException):
00353     """@brief The next tree mode does not match the expected type."""
00354 
00355     def __init__(self, expecting, input):
00356         RecognitionException.__init__(self, input)
00357         
00358         self.expecting = expecting
00359 
00360     def __str__(self):
00361         return "MismatchedTreeNodeException(%r!=%r)" % (
00362             self.getUnexpectedType(), self.expecting
00363             )
00364     __repr__ = __str__


rve_interface_gen
Author(s): Josh Faust
autogenerated on Wed Dec 11 2013 14:31:00