ScoDoc/config/softs/pyExcelerator-0.6.3a.patched/pyExcelerator/antlr.py

2801 lines
80 KiB
Python
Executable File

## This file is part of PyANTLR. See LICENSE.txt for license
## details..........Copyright (C) Wolfgang Haefelinger, 2004.
## get sys module
import sys
version = sys.version.split()[0]
if version < '2.2.1':
False = 0
if version < '2.3':
True = not False
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### global symbols ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### ANTLR Standard Tokens
SKIP = -1
INVALID_TYPE = 0
EOF_TYPE = 1
EOF = 1
NULL_TREE_LOOKAHEAD = 3
MIN_USER_TYPE = 4
### ANTLR's EOF Symbol
EOF_CHAR = ''
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### general functions ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
def error(fmt,*args):
if fmt:
print "error: ", fmt % tuple(args)
def ifelse(cond,_then,_else):
if cond :
r = _then
else:
r = _else
return r
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### ANTLR Exceptions ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class ANTLRException(Exception):
def __init__(self, *args):
Exception.__init__(self, *args)
class RecognitionException(ANTLRException):
def __init__(self, *args):
ANTLRException.__init__(self, *args)
self.fileName = None
self.line = -1
self.column = -1
if len(args) >= 2:
self.fileName = args[1]
if len(args) >= 3:
self.line = args[2]
if len(args) >= 4:
self.column = args[3]
def __str__(self):
buf = ['']
if self.fileName:
buf.append(self.fileName + ":")
if self.line != -1:
if not self.fileName:
buf.append("line ")
buf.append(str(self.line))
if self.column != -1:
buf.append(":" + str(self.column))
buf.append(":")
buf.append(" ")
return str('').join(buf)
__repr__ = __str__
class NoViableAltException(RecognitionException):
def __init__(self, *args):
RecognitionException.__init__(self, *args)
self.token = None
self.node = None
if isinstance(args[0],AST):
self.node = args[0]
elif isinstance(args[0],Token):
self.token = args[0]
else:
raise TypeError("NoViableAltException requires Token or AST argument")
def __str__(self):
if self.token:
line = self.token.getLine()
col = self.token.getColumn()
text = self.token.getText()
return "unexpected symbol at line %s (column %s): \"%s\"" % (line,col,text)
if self.node == ASTNULL:
return "unexpected end of subtree"
assert self.node
### hackish, we assume that an AST contains method getText
return "unexpected node: %s" % (self.node.getText())
__repr__ = __str__
class NoViableAltForCharException(RecognitionException):
def __init__(self, *args):
self.foundChar = None
if len(args) == 2:
self.foundChar = args[0]
scanner = args[1]
RecognitionException.__init__(self, "NoViableAlt",
scanner.getFilename(),
scanner.getLine(),
scanner.getColumn())
elif len(args) == 4:
self.foundChar = args[0]
fileName = args[1]
line = args[2]
column = args[3]
RecognitionException.__init__(self, "NoViableAlt",
fileName, line, column)
else:
RecognitionException.__init__(self, "NoViableAlt",
'', -1, -1)
def __str__(self):
mesg = "unexpected char: "
if self.foundChar >= ' ' and self.foundChar <= '~':
mesg += "'" + self.foundChar + "'"
elif self.foundChar:
mesg += "0x" + hex(ord(self.foundChar)).upper()[2:]
else:
mesg += "<None>"
return mesg
__repr__ = __str__
class SemanticException(RecognitionException):
def __init__(self, *args):
RecognitionException.__init__(self, *args)
class MismatchedCharException(RecognitionException):
NONE = 0
CHAR = 1
NOT_CHAR = 2
RANGE = 3
NOT_RANGE = 4
SET = 5
NOT_SET = 6
def __init__(self, *args):
self.args = args
if len(args) == 5:
# Expected range / not range
if args[3]:
self.mismatchType = MismatchedCharException.NOT_RANGE
else:
self.mismatchType = MismatchedCharException.RANGE
self.foundChar = args[0]
self.expecting = args[1]
self.upper = args[2]
self.scanner = args[4]
RecognitionException.__init__(self, "Mismatched char range",
self.scanner.getFilename(),
self.scanner.getLine(),
self.scanner.getColumn())
elif len(args) == 4 and isinstance(args[1], str):
# Expected char / not char
if args[2]:
self.mismatchType = MismatchedCharException.NOT_CHAR
else:
self.mismatchType = MismatchedCharException.CHAR
self.foundChar = args[0]
self.expecting = args[1]
self.scanner = args[3]
RecognitionException.__init__(self, "Mismatched char",
self.scanner.getFilename(),
self.scanner.getLine(),
self.scanner.getColumn())
elif len(args) == 4 and isinstance(args[1], BitSet):
# Expected BitSet / not BitSet
if args[2]:
self.mismatchType = MismatchedCharException.NOT_SET
else:
self.mismatchType = MismatchedCharException.SET
self.foundChar = args[0]
self.set = args[1]
self.scanner = args[3]
RecognitionException.__init__(self, "Mismatched char set",
self.scanner.getFilename(),
self.scanner.getLine(),
self.scanner.getColumn())
else:
self.mismatchType = MismatchedCharException.NONE
RecognitionException.__init__(self, "Mismatched char")
## Append a char to the msg buffer. If special,
# then show escaped version
#
def appendCharName(self, sb, c):
if not c or c == 65535:
# 65535 = (char) -1 = EOF
sb.append("'<EOF>'")
elif c == '\n':
sb.append("'\\n'")
elif c == '\r':
sb.append("'\\r'");
elif c == '\t':
sb.append("'\\t'")
else:
sb.append('\'' + c + '\'')
##
# Returns an error message with line number/column information
#
def __str__(self):
sb = ['']
sb.append(RecognitionException.__str__(self))
if self.mismatchType == MismatchedCharException.CHAR:
sb.append("expecting ")
self.appendCharName(sb, self.expecting)
sb.append(", found ")
self.appendCharName(sb, self.foundChar)
elif self.mismatchType == MismatchedCharException.NOT_CHAR:
sb.append("expecting anything but '")
self.appendCharName(sb, self.expecting)
sb.append("'; got it anyway")
elif self.mismatchType in [MismatchedCharException.RANGE, MismatchedCharException.NOT_RANGE]:
sb.append("expecting char ")
if self.mismatchType == MismatchedCharException.NOT_RANGE:
sb.append("NOT ")
sb.append("in range: ")
appendCharName(sb, self.expecting)
sb.append("..")
appendCharName(sb, self.upper)
sb.append(", found ")
appendCharName(sb, self.foundChar)
elif self.mismatchType in [MismatchedCharException.SET, MismatchedCharException.NOT_SET]:
sb.append("expecting ")
if self.mismatchType == MismatchedCharException.NOT_SET:
sb.append("NOT ")
sb.append("one of (")
for i in range(len(self.set)):
self.appendCharName(sb, self.set[i])
sb.append("), found ")
self.appendCharName(sb, self.foundChar)
return str().join(sb).strip()
__repr__ = __str__
class MismatchedTokenException(RecognitionException):
NONE = 0
TOKEN = 1
NOT_TOKEN = 2
RANGE = 3
NOT_RANGE = 4
SET = 5
NOT_SET = 6
def __init__(self, *args):
self.args = args
self.tokenNames = []
self.token = None
self.tokenText = ''
self.node = None
if len(args) == 6:
# Expected range / not range
if args[3]:
self.mismatchType = MismatchedTokenException.NOT_RANGE
else:
self.mismatchType = MismatchedTokenException.RANGE
self.tokenNames = args[0]
self.expecting = args[2]
self.upper = args[3]
self.fileName = args[5]
elif len(args) == 4 and isinstance(args[2], int):
# Expected token / not token
if args[3]:
self.mismatchType = MismatchedTokenException.NOT_TOKEN
else:
self.mismatchType = MismatchedTokenException.TOKEN
self.tokenNames = args[0]
self.expecting = args[2]
elif len(args) == 4 and isinstance(args[2], BitSet):
# Expected BitSet / not BitSet
if args[3]:
self.mismatchType = MismatchedTokenException.NOT_SET
else:
self.mismatchType = MismatchedTokenException.SET
self.tokenNames = args[0]
self.set = args[2]
else:
self.mismatchType = MismatchedTokenException.NONE
RecognitionException.__init__(self, "Mismatched Token: expecting any AST node", "<AST>", -1, -1)
if len(args) >= 2:
if isinstance(args[1],Token):
self.token = args[1]
self.tokenText = self.token.getText()
RecognitionException.__init__(self, "Mismatched Token",
self.fileName,
self.token.getLine(),
self.token.getColumn())
elif isinstance(args[1],AST):
self.node = args[1]
self.tokenText = str(self.node)
RecognitionException.__init__(self, "Mismatched Token",
"<AST>",
self.node.getLine(),
self.node.getColumn())
else:
self.tokenText = "<empty tree>"
RecognitionException.__init__(self, "Mismatched Token",
"<AST>", -1, -1)
def appendTokenName(self, sb, tokenType):
if tokenType == INVALID_TYPE:
sb.append("<Set of tokens>")
elif tokenType < 0 or tokenType >= len(self.tokenNames):
sb.append("<" + str(tokenType) + ">")
else:
sb.append(self.tokenNames[tokenType])
##
# Returns an error message with line number/column information
#
def __str__(self):
sb = ['']
sb.append(RecognitionException.__str__(self))
if self.mismatchType == MismatchedTokenException.TOKEN:
sb.append("expecting ")
self.appendTokenName(sb, self.expecting)
sb.append(", found " + self.tokenText)
elif self.mismatchType == MismatchedTokenException.NOT_TOKEN:
sb.append("expecting anything but '")
self.appendTokenName(sb, self.expecting)
sb.append("'; got it anyway")
elif self.mismatchType in [MismatchedTokenException.RANGE, MismatchedTokenException.NOT_RANGE]:
sb.append("expecting token ")
if self.mismatchType == MismatchedTokenException.NOT_RANGE:
sb.append("NOT ")
sb.append("in range: ")
appendTokenName(sb, self.expecting)
sb.append("..")
appendTokenName(sb, self.upper)
sb.append(", found " + self.tokenText)
elif self.mismatchType in [MismatchedTokenException.SET, MismatchedTokenException.NOT_SET]:
sb.append("expecting ")
if self.mismatchType == MismatchedTokenException.NOT_SET:
sb.append("NOT ")
sb.append("one of (")
for i in range(len(self.set)):
self.appendTokenName(sb, self.set[i])
sb.append("), found " + self.tokenText)
return str().join(sb).strip()
__repr__ = __str__
class TokenStreamException(ANTLRException):
def __init__(self, *args):
ANTLRException.__init__(self, *args)
# Wraps an Exception in a TokenStreamException
class TokenStreamIOException(TokenStreamException):
def __init__(self, *args):
if args and isinstance(args[0], Exception):
io = args[0]
TokenStreamException.__init__(self, str(io))
self.io = io
else:
TokenStreamException.__init__(self, *args)
self.io = self
# Wraps a RecognitionException in a TokenStreamException
class TokenStreamRecognitionException(TokenStreamException):
def __init__(self, *args):
if args and isinstance(args[0], RecognitionException):
recog = args[0]
TokenStreamException.__init__(self, str(recog))
self.recog = recog
else:
raise TypeError("TokenStreamRecognitionException requires RecognitionException argument")
def __str__(self):
return str(self.recog)
__repr__ = __str__
class TokenStreamRetryException(TokenStreamException):
def __init__(self, *args):
TokenStreamException.__init__(self, *args)
class CharStreamException(ANTLRException):
def __init__(self, *args):
ANTLRException.__init__(self, *args)
# Wraps an Exception in a CharStreamException
class CharStreamIOException(CharStreamException):
def __init__(self, *args):
if args and isinstance(args[0], Exception):
io = args[0]
CharStreamException.__init__(self, str(io))
self.io = io
else:
CharStreamException.__init__(self, *args)
self.io = self
class TryAgain(Exception):
pass
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### Token ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class Token(object):
SKIP = -1
INVALID_TYPE = 0
EOF_TYPE = 1
EOF = 1
NULL_TREE_LOOKAHEAD = 3
MIN_USER_TYPE = 4
def __init__(self,**argv):
try:
self.type = argv['type']
except:
self.type = INVALID_TYPE
try:
self.text = argv['text']
except:
self.text = "<no text>"
def isEOF(self):
return (self.type == EOF_TYPE)
def getColumn(self):
return 0
def getLine(self):
return 0
def getFilename(self):
return None
def setFilename(self,name):
return self
def getText(self):
return "<no text>"
def setText(self,text):
if isinstance(text,str):
pass
else:
raise TypeError("Token.setText requires string argument")
return self
def setColumn(self,column):
return self
def setLine(self,line):
return self
def getType(self):
return self.type
def setType(self,type):
if isinstance(type,int):
self.type = type
else:
raise TypeError("Token.setType requires integer argument")
return self
def toString(self):
## not optimal
type_ = self.type
if type_ == 3:
tval = 'NULL_TREE_LOOKAHEAD'
elif type_ == 1:
tval = 'EOF_TYPE'
elif type_ == 0:
tval = 'INVALID_TYPE'
elif type_ == -1:
tval = 'SKIP'
else:
tval = type_
return '["%s",<%s>]' % (self.getText(),tval)
__str__ = toString
__repr__ = toString
### static attribute ..
Token.badToken = Token( type=INVALID_TYPE, text="<no text>")
if __name__ == "__main__":
print "testing .."
T = Token.badToken
print T
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### CommonToken ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class CommonToken(Token):
def __init__(self,**argv):
Token.__init__(self,**argv)
self.line = 0
self.col = 0
try:
self.line = argv['line']
except:
pass
try:
self.col = argv['col']
except:
pass
def getLine(self):
return self.line
def getText(self):
return self.text
def getColumn(self):
return self.col
def setLine(self,line):
self.line = line
return self
def setText(self,text):
self.text = text
return self
def setColumn(self,col):
self.col = col
return self
def toString(self):
## not optimal
type_ = self.type
if type_ == 3:
tval = 'NULL_TREE_LOOKAHEAD'
elif type_ == 1:
tval = 'EOF_TYPE'
elif type_ == 0:
tval = 'INVALID_TYPE'
elif type_ == -1:
tval = 'SKIP'
else:
tval = type_
d = {
'text' : self.text,
'type' : tval,
'line' : self.line,
'colm' : self.col
}
fmt = '["%(text)s",<%(type)s>,line=%(line)s,col=%(colm)s]'
return fmt % d
__str__ = toString
__repr__ = toString
if __name__ == '__main__' :
T = CommonToken()
print T
T = CommonToken(col=15,line=1,text="some text", type=5)
print T
T = CommonToken()
T.setLine(1).setColumn(15).setText("some text").setType(5)
print T
print T.getLine()
print T.getColumn()
print T.getText()
print T.getType()
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### CommonHiddenStreamToken ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class CommonHiddenStreamToken(CommonToken):
def __init__(self,*args):
CommonToken.__init__(self,*args)
self.hiddenBefore = None
self.hiddenAfter = None
def getHiddenAfter(self):
return self.hiddenAfter
def getHiddenBefore(self):
return self.hiddenBefore
def setHiddenAfter(self,t):
self.hiddenAfter = t
def setHiddenBefore(self, t):
self.hiddenBefore = t
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### Queue ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
## Shall be a circular buffer on tokens ..
class Queue(object):
def __init__(self):
self.buffer = [] # empty list
def append(self,item):
self.buffer.append(item)
def elementAt(self,index):
return self.buffer[index]
def reset(self):
self.buffer = []
def removeFirst(self):
self.buffer.pop(0)
def length(self):
return len(self.buffer)
def __str__(self):
return str(self.buffer)
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### InputBuffer ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class InputBuffer(object):
def __init__(self):
self.nMarkers = 0
self.markerOffset = 0
self.numToConsume = 0
self.queue = Queue()
def __str__(self):
return "(%s,%s,%s,%s)" % (
self.nMarkers,
self.markerOffset,
self.numToConsume,
self.queue)
def __repr__(self):
return str(self)
def commit(self):
self.nMarkers -= 1
def consume(self) :
self.numToConsume += 1
## probably better to return a list of items
## because of unicode. Or return a unicode
## string ..
def getLAChars(self) :
i = self.markerOffset
n = self.queue.length()
s = ''
while i<n:
s += self.queue.elementAt(i)
return s
## probably better to return a list of items
## because of unicode chars
def getMarkedChars(self) :
s = ''
i = 0
n = self.markerOffset
while i<n:
s += self.queue.elementAt(i)
return s
def isMarked(self) :
return self.nMarkers != 0
def fill(self,k):
### abstract method
raise NotImplementedError()
def LA(self,k) :
self.fill(k)
return self.queue.elementAt(self.markerOffset + k - 1)
def mark(self) :
self.syncConsume()
self.nMarkers += 1
return self.markerOffset
def rewind(self,mark) :
self.syncConsume()
self.markerOffset = mark
self.nMarkers -= 1
def reset(self) :
self.nMarkers = 0
self.markerOffset = 0
self.numToConsume = 0
self.queue.reset()
def syncConsume(self) :
while self.numToConsume > 0:
if self.nMarkers > 0:
# guess mode -- leave leading characters and bump offset.
self.markerOffset += 1
else:
# normal mode -- remove first character
self.queue.removeFirst()
self.numToConsume -= 1
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### CharBuffer ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class CharBuffer(InputBuffer):
def __init__(self,reader):
##assert isinstance(reader,file)
super(CharBuffer,self).__init__()
## a reader is supposed to be anything that has
## a method 'read(int)'.
self.input = reader
def __str__(self):
base = super(CharBuffer,self).__str__()
return "CharBuffer{%s,%s" % (base,str(input))
def fill(self,amount):
try:
self.syncConsume()
while self.queue.length() < (amount + self.markerOffset) :
## retrieve just one char - what happend at end
## of input?
c = self.input.read(1)
### python's behaviour is to return the empty string on
### EOF, ie. no exception whatsoever is thrown. An empty
### python string has the nice feature that it is of
### type 'str' and "not ''" would return true. Contrary,
### one can't do this: '' in 'abc'. This should return
### false, but all we get is then a TypeError as an
### empty string is not a character.
### Let's assure then that we have either seen a
### character or an empty string (EOF).
assert len(c) == 0 or len(c) == 1
### And it shall be of type string (ASCII or UNICODE).
assert isinstance(c,str) or isinstance(c,unicode)
### Just append EOF char to buffer. Note that buffer may
### contain then just more than one EOF char ..
### use unicode chars instead of ASCII ..
self.queue.append(c)
except Exception,e:
raise CharStreamIOException(e)
##except: # (mk) Cannot happen ...
##error ("unexpected exception caught ..")
##assert 0
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### LexerSharedInputState ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class LexerSharedInputState(object):
def __init__(self,ibuf):
assert isinstance(ibuf,InputBuffer)
self.input = ibuf
self.column = 1
self.line = 1
self.tokenStartColumn = 1
self.tokenStartLine = 1
self.guessing = 0
self.filename = None
def reset(self):
self.column = 1
self.line = 1
self.tokenStartColumn = 1
self.tokenStartLine = 1
self.guessing = 0
self.filename = None
self.input.reset()
def LA(self,k):
return self.input.LA(k)
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### TokenStream ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class TokenStream(object):
def nextToken(self):
pass
def __iter__(self):
return TokenStreamIterator(self)
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### TokenStreamIterator ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class TokenStreamIterator(object):
def __init__(self,inst):
if isinstance(inst,TokenStream):
self.inst = inst
return
raise TypeError("TokenStreamIterator requires TokenStream object")
def next(self):
assert self.inst
item = self.inst.nextToken()
if not item or item.isEOF():
raise StopIteration()
return item
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### TokenStreamSelector ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class TokenStreamSelector(TokenStream):
def __init__(self):
self._input = None
self._stmap = {}
self._stack = []
def addInputStream(self,stream,key):
self._stmap[key] = stream
def getCurrentStream(self):
return self._input
def getStream(self,sname):
try:
stream = self._stmap[sname]
except:
raise ValueError("TokenStream " + sname + " not found");
return stream;
def nextToken(self):
while 1:
try:
return self._input.nextToken()
except TokenStreamRetryException,r:
### just retry "forever"
pass
def pop(self):
stream = self._stack.pop();
self.select(stream);
return stream;
def push(self,arg):
self._stack.append(self._input);
self.select(arg)
def retry(self):
raise TokenStreamRetryException()
def select(self,arg):
if isinstance(arg,TokenStream):
self._input = arg
return
if isinstance(arg,str):
self._input = self.getStream(arg)
return
raise TypeError("TokenStreamSelector.select requires " +
"TokenStream or string argument")
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### TokenStreamBasicFilter ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class TokenStreamBasicFilter(TokenStream):
def __init__(self,input):
self.input = input;
self.discardMask = BitSet()
def discard(self,arg):
if isinstance(arg,int):
self.discardMask.add(arg)
return
if isinstance(arg,BitSet):
self.discardMark = arg
return
raise TypeError("TokenStreamBasicFilter.discard requires" +
"integer or BitSet argument")
def nextToken(self):
tok = self.input.nextToken()
while tok and self.discardMask.member(tok.getType()):
tok = self.input.nextToken()
return tok
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### TokenStreamHiddenTokenFilter ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class TokenStreamHiddenTokenFilter(TokenStreamBasicFilter):
def __init__(self,input):
TokenStreamBasicFilter.__init__(self,input)
self.hideMask = BitSet()
self.nextMonitoredToken = None
self.lastHiddenToken = None
self.firstHidden = None
def consume(self):
self.nextMonitoredToken = self.input.nextToken()
def consumeFirst(self):
self.consume()
p = None;
while self.hideMask.member(self.LA(1).getType()) or \
self.discardMask.member(self.LA(1).getType()):
if self.hideMask.member(self.LA(1).getType()):
if not p:
p = self.LA(1)
else:
p.setHiddenAfter(self.LA(1))
self.LA(1).setHiddenBefore(p)
p = self.LA(1)
self.lastHiddenToken = p
if not self.firstHidden:
self.firstHidden = p
self.consume()
def getDiscardMask(self):
return self.discardMask
def getHiddenAfter(self,t):
return t.getHiddenAfter()
def getHiddenBefore(self,t):
return t.getHiddenBefore()
def getHideMask(self):
return self.hideMask
def getInitialHiddenToken(self):
return self.firstHidden
def hide(self,m):
if isinstance(m,int):
self.hideMask.add(m)
return
if isinstance(m.BitMask):
self.hideMask = m
return
def LA(self,i):
return self.nextMonitoredToken
def nextToken(self):
if not self.LA(1):
self.consumeFirst()
monitored = self.LA(1)
monitored.setHiddenBefore(self.lastHiddenToken)
self.lastHiddenToken = None
self.consume()
p = monitored
while self.hideMask.member(self.LA(1).getType()) or \
self.discardMask.member(self.LA(1).getType()):
if self.hideMask.member(self.LA(1).getType()):
p.setHiddenAfter(self.LA(1))
if p != monitored:
self.LA(1).setHiddenBefore(p)
p = self.lastHiddenToken = self.LA(1)
self.consume()
return monitored
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### StringBuffer ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class StringBuffer:
def __init__(self,string=None):
if string:
self.text = list(string)
else:
self.text = []
def setLength(self,sz):
if not sz :
self.text = []
return
assert sz>0
if sz >= self.length():
return
### just reset to empty buffer
self.text = self.text[0:sz]
def length(self):
return len(self.text)
def append(self,c):
self.text.append(c)
### return buffer as string. Arg 'a' is used as index
## into the buffer and 2nd argument shall be the length.
## If 2nd args is absent, we return chars till end of
## buffer starting with 'a'.
def getString(self,a=None,length=None):
if not a :
a = 0
assert a>=0
if a>= len(self.text) :
return ""
if not length:
## no second argument
L = self.text[a:]
else:
assert (a+length) <= len(self.text)
b = a + length
L = self.text[a:b]
s = ""
for x in L : s += x
return s
toString = getString ## alias
def __str__(self):
return str(self.text)
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### Reader ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
## When reading Japanese chars, it happens that a stream returns a
## 'char' of length 2. This looks like a bug in the appropriate
## codecs - but I'm rather unsure about this. Anyway, if this is
## the case, I'm going to split this string into a list of chars
## and put them on hold, ie. on a buffer. Next time when called
## we read from buffer until buffer is empty.
## wh: nov, 25th -> problem does not appear in Python 2.4.0.c1.
class Reader(object):
def __init__(self,stream):
self.cin = stream
self.buf = []
def read(self,num):
assert num==1
if len(self.buf):
return self.buf.pop()
## Read a char - this may return a string.
## Is this a bug in codecs/Python?
c = self.cin.read(1)
if not c or len(c)==1:
return c
L = list(c)
L.reverse()
for x in L:
self.buf.append(x)
## read one char ..
return self.read(1)
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### CharScanner ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class CharScanner(TokenStream):
## class members
NO_CHAR = 0
EOF_CHAR = '' ### EOF shall be the empty string.
def __init__(self, *argv, **kwargs):
super(CharScanner, self).__init__()
self.saveConsumedInput = True
self.tokenClass = None
self.caseSensitive = True
self.caseSensitiveLiterals = True
self.literals = None
self.tabsize = 8
self._returnToken = None
self.commitToPath = False
self.traceDepth = 0
self.text = StringBuffer()
self.hashString = hash(self)
self.setTokenObjectClass(CommonToken)
self.setInput(*argv)
def __iter__(self):
return CharScannerIterator(self)
def setInput(self,*argv):
## case 1:
## if there's no arg we default to read from
## standard input
if not argv:
import sys
self.setInput(sys.stdin)
return
## get 1st argument
arg1 = argv[0]
## case 2:
## if arg1 is a string, we assume it's a file name
## and open a stream using 2nd argument as open
## mode. If there's no 2nd argument we fall back to
## mode '+rb'.
if isinstance(arg1,str):
f = open(arg1,"rb")
self.setInput(f)
self.setFilename(arg1)
return
## case 3:
## if arg1 is a file we wrap it by a char buffer (
## some additional checks?? No, can't do this in
## general).
if isinstance(arg1,file):
self.setInput(CharBuffer(arg1))
return
## case 4:
## if arg1 is of type SharedLexerInputState we use
## argument as is.
if isinstance(arg1,LexerSharedInputState):
self.inputState = arg1
return
## case 5:
## check whether argument type is of type input
## buffer. If so create a SharedLexerInputState and
## go ahead.
if isinstance(arg1,InputBuffer):
self.setInput(LexerSharedInputState(arg1))
return
## case 6:
## check whether argument type has a method read(int)
## If so create CharBuffer ...
try:
if arg1.read:
rd = Reader(arg1)
cb = CharBuffer(rd)
ss = LexerSharedInputState(cb)
self.inputState = ss
return
except:
pass
## case 7:
## raise wrong argument exception
raise TypeError(argv)
def setTabSize(self,size) :
self.tabsize = size
def getTabSize(self) :
return self.tabsize
def setCaseSensitive(self,t) :
self.caseSensitive = t
def setCommitToPath(self,commit) :
self.commitToPath = commit
def setFilename(self,f) :
self.inputState.filename = f
def setLine(self,line) :
self.inputState.line = line
def setText(self,s) :
self.resetText()
self.text.append(s)
def getCaseSensitive(self) :
return self.caseSensitive
def getCaseSensitiveLiterals(self) :
return self.caseSensitiveLiterals
def getColumn(self) :
return self.inputState.column
def setColumn(self,c) :
self.inputState.column = c
def getCommitToPath(self) :
return self.commitToPath
def getFilename(self) :
return self.inputState.filename
def getInputBuffer(self) :
return self.inputState.input
def getInputState(self) :
return self.inputState
def setInputState(self,state) :
assert isinstance(state,LexerSharedInputState)
self.inputState = state
def getLine(self) :
return self.inputState.line
def getText(self) :
return str(self.text)
def getTokenObject(self) :
return self._returnToken
def LA(self,i) :
c = self.inputState.input.LA(i)
if not self.caseSensitive:
### E0006
c = c.__class__.lower(c)
return c
def makeToken(self,type) :
try:
## dynamically load a class
assert self.tokenClass
tok = self.tokenClass()
tok.setType(type)
tok.setColumn(self.inputState.tokenStartColumn)
tok.setLine(self.inputState.tokenStartLine)
return tok
except:
self.panic("unable to create new token")
return Token.badToken
def mark(self) :
return self.inputState.input.mark()
def _match_bitset(self,b) :
if b.member(self.LA(1)):
self.consume()
else:
raise MismatchedCharException(self.LA(1), b, False, self)
def _match_string(self,s) :
for c in s:
if self.LA(1) == c:
self.consume()
else:
raise MismatchedCharException(self.LA(1), c, False, self)
def match(self,item):
if isinstance(item,str) or isinstance(item,unicode):
return self._match_string(item)
else:
return self._match_bitset(item)
def matchNot(self,c) :
if self.LA(1) != c:
self.consume()
else:
raise MismatchedCharException(self.LA(1), c, True, self)
def matchRange(self,c1,c2) :
if self.LA(1) < c1 or self.LA(1) > c2 :
raise MismatchedCharException(self.LA(1), c1, c2, False, self)
else:
self.consume()
def newline(self) :
self.inputState.line += 1
self.inputState.column = 1
def tab(self) :
c = self.getColumn()
nc = ( ((c-1)/self.tabsize) + 1) * self.tabsize + 1
self.setColumn(nc)
def panic(self,s='') :
print "CharScanner: panic: " + s
sys.exit(1)
def reportError(self,ex) :
print ex
def reportError(self,s) :
if not self.getFilename():
print "error: " + str(s)
else:
print self.getFilename() + ": error: " + str(s)
def reportWarning(self,s) :
if not self.getFilename():
print "warning: " + str(s)
else:
print self.getFilename() + ": warning: " + str(s)
def resetText(self) :
self.text.setLength(0)
self.inputState.tokenStartColumn = self.inputState.column
self.inputState.tokenStartLine = self.inputState.line
def rewind(self,pos) :
self.inputState.input.rewind(pos)
def setTokenObjectClass(self,cl):
self.tokenClass = cl
def testForLiteral(self,token):
if not token:
return
assert isinstance(token,Token)
_type = token.getType()
## special tokens can't be literals
if _type in [SKIP,INVALID_TYPE,EOF_TYPE,NULL_TREE_LOOKAHEAD] :
return
_text = token.getText()
if not _text:
return
assert isinstance(_text,str) or isinstance(_text,unicode)
_type = self.testLiteralsTable(_text,_type)
token.setType(_type)
return _type
def testLiteralsTable(self,*args):
if isinstance(args[0],str) or isinstance(args[0],unicode):
s = args[0]
i = args[1]
else:
s = self.text.getString()
i = args[0]
## check whether integer has been given
if not isinstance(i,int):
assert isinstance(i,int)
## check whether we have a dict
assert isinstance(self.literals,dict)
try:
## E0010
if not self.caseSensitiveLiterals:
s = s.__class__.lower(s)
i = self.literals[s]
except:
pass
return i
def toLower(self,c):
return c.__class__.lower()
def traceIndent(self):
print ' ' * self.traceDepth
def traceIn(self,rname):
self.traceDepth += 1
self.traceIndent()
print "> lexer %s c== %s" % (rname,self.LA(1))
def traceOut(self,rname):
self.traceIndent()
print "< lexer %s c== %s" % (rname,self.LA(1))
self.traceDepth -= 1
def uponEOF(self):
pass
def append(self,c):
if self.saveConsumedInput :
self.text.append(c)
def commit(self):
self.inputState.input.commit()
def consume(self):
if not self.inputState.guessing:
c = self.LA(1)
if self.caseSensitive:
self.append(c)
else:
# use input.LA(), not LA(), to get original case
# CharScanner.LA() would toLower it.
c = self.inputState.input.LA(1)
self.append(c)
if c and c in "\t":
self.tab()
else:
self.inputState.column += 1
self.inputState.input.consume()
## Consume chars until one matches the given char
def consumeUntil_char(self,c):
while self.LA(1) != EOF_CHAR and self.LA(1) != c:
self.consume()
## Consume chars until one matches the given set
def consumeUntil_bitset(self,bitset):
while self.LA(1) != EOF_CHAR and not self.set.member(self.LA(1)):
self.consume()
### If symbol seen is EOF then generate and set token, otherwise
### throw exception.
def default(self,la1):
if not la1 :
self.uponEOF()
self._returnToken = self.makeToken(EOF_TYPE)
else:
self.raise_NoViableAlt(la1)
def filterdefault(self,la1,*args):
if not la1:
self.uponEOF()
self._returnToken = self.makeToken(EOF_TYPE)
return
if not args:
self.consume()
raise TryAgain()
else:
### apply filter object
self.commit();
try:
func=args[0]
args=args[1:]
apply(func,args)
except RecognitionException, e:
## catastrophic failure
self.reportError(e);
self.consume();
raise TryAgain()
def raise_NoViableAlt(self,la1=None):
if not la1: la1 = self.LA(1)
fname = self.getFilename()
line = self.getLine()
col = self.getColumn()
raise NoViableAltForCharException(la1,fname,line,col)
def set_return_token(self,_create,_token,_ttype,_offset):
if _create and not _token and (not _ttype == SKIP):
string = self.text.getString(_offset)
_token = self.makeToken(_ttype)
_token.setText(string)
self._returnToken = _token
return _token
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### CharScannerIterator ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class CharScannerIterator:
def __init__(self,inst):
if isinstance(inst,CharScanner):
self.inst = inst
return
raise TypeError("CharScannerIterator requires CharScanner object")
def next(self):
assert self.inst
item = self.inst.nextToken()
if not item or item.isEOF():
raise StopIteration()
return item
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### BitSet ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### I'm assuming here that a long is 64bits. It appears however, that
### a long is of any size. That means we can use a single long as the
### bitset (!), ie. Python would do almost all the work (TBD).
class BitSet(object):
BITS = 64
NIBBLE = 4
LOG_BITS = 6
MOD_MASK = BITS -1
def __init__(self,data=None):
if not data:
BitSet.__init__(self,[long(0)])
return
if isinstance(data,int):
BitSet.__init__(self,[long(data)])
return
if isinstance(data,long):
BitSet.__init__(self,[data])
return
if not isinstance(data,list):
raise TypeError("BitSet requires integer, long, or " +
"list argument")
for x in data:
if not isinstance(x,long):
raise TypeError(self,"List argument item is " +
"not a long: %s" % (x))
self.data = data
def __str__(self):
bits = len(self.data) * BitSet.BITS
s = ""
for i in xrange(0,bits):
if self.at(i):
s += "1"
else:
s += "o"
if not ((i+1) % 10):
s += '|%s|' % (i+1)
return s
def __repr__(self):
return str(self)
def member(self,item):
if not item:
return False
if isinstance(item,int):
return self.at(item)
if not (isinstance(item,str) or isinstance(item,unicode)):
raise TypeError(self,"char or unichar expected: %s" % (item))
## char is a (unicode) string with at most lenght 1, ie.
## a char.
if len(item) != 1:
raise TypeError(self,"char expected: %s" % (item))
### handle ASCII/UNICODE char
num = ord(item)
### check whether position num is in bitset
return self.at(num)
def wordNumber(self,bit):
return bit >> BitSet.LOG_BITS
def bitMask(self,bit):
pos = bit & BitSet.MOD_MASK ## bit mod BITS
return (1L << pos)
def set(self,bit,on=True):
# grow bitset as required (use with care!)
i = self.wordNumber(bit)
mask = self.bitMask(bit)
if i>=len(self.data):
d = i - len(self.data) + 1
for x in xrange(0,d):
self.data.append(0L)
assert len(self.data) == i+1
if on:
self.data[i] |= mask
else:
self.data[i] &= (~mask)
### make add an alias for set
add = set
def off(self,bit,off=True):
self.set(bit,not off)
def at(self,bit):
i = self.wordNumber(bit)
v = self.data[i]
m = self.bitMask(bit)
return v & m
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### some further funcs ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
def illegalarg_ex(func):
raise ValueError(
"%s is only valid if parser is built for debugging" %
(func.func_name))
def runtime_ex(func):
raise RuntimeException(
"%s is only valid if parser is built for debugging" %
(func.func_name))
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### TokenBuffer ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class TokenBuffer(object):
def __init__(self,stream):
self.input = stream
self.nMarkers = 0
self.markerOffset = 0
self.numToConsume = 0
self.queue = Queue()
def reset(self) :
self.nMarkers = 0
self.markerOffset = 0
self.numToConsume = 0
self.queue.reset()
def consume(self) :
self.numToConsume += 1
def fill(self, amount):
self.syncConsume()
while self.queue.length() < (amount + self.markerOffset):
self.queue.append(self.input.nextToken())
def getInput(self):
return self.input
def LA(self,k) :
self.fill(k)
return self.queue.elementAt(self.markerOffset + k - 1).type
def LT(self,k) :
self.fill(k)
return self.queue.elementAt(self.markerOffset + k - 1)
def mark(self) :
self.syncConsume()
self.nMarkers += 1
return self.markerOffset
def rewind(self,mark) :
self.syncConsume()
self.markerOffset = mark
self.nMarkers -= 1
def syncConsume(self) :
while self.numToConsume > 0:
if self.nMarkers > 0:
# guess mode -- leave leading characters and bump offset.
self.markerOffset += 1
else:
# normal mode -- remove first character
self.queue.removeFirst()
self.numToConsume -= 1
def __str__(self):
return "(%s,%s,%s,%s,%s)" % (
self.input,
self.nMarkers,
self.markerOffset,
self.numToConsume,
self.queue)
def __repr__(self):
return str(self)
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### ParserSharedInputState ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class ParserSharedInputState(object):
def __init__(self):
self.input = None
self.reset()
def reset(self):
self.guessing = 0
self.filename = None
if self.input:
self.input.reset()
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### Parser ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class Parser(object):
def __init__(self, *args, **kwargs):
self.tokenNames = None
self.returnAST = None
self.astFactory = None
self.tokenTypeToASTClassMap = {}
self.ignoreInvalidDebugCalls = False
self.traceDepth = 0
if not args:
self.inputState = ParserSharedInputState()
return
arg0 = args[0]
assert isinstance(arg0,ParserSharedInputState)
self.inputState = arg0
return
def getTokenTypeToASTClassMap(self):
return self.tokenTypeToASTClassMap
def addMessageListener(self, l):
if not self.ignoreInvalidDebugCalls:
illegalarg_ex(addMessageListener)
def addParserListener(self,l) :
if (not self.ignoreInvalidDebugCalls) :
illegalarg_ex(addParserListener)
def addParserMatchListener(self, l) :
if (not self.ignoreInvalidDebugCalls) :
illegalarg_ex(addParserMatchListener)
def addParserTokenListener(self, l) :
if (not self.ignoreInvalidDebugCalls):
illegalarg_ex(addParserTokenListener)
def addSemanticPredicateListener(self, l) :
if (not self.ignoreInvalidDebugCalls):
illegalarg_ex(addSemanticPredicateListener)
def addSyntacticPredicateListener(self, l) :
if (not self.ignoreInvalidDebugCalls):
illegalarg_ex(addSyntacticPredicateListener)
def addTraceListener(self, l) :
if (not self.ignoreInvalidDebugCalls):
illegalarg_ex(addTraceListener)
def consume(self):
raise NotImplementedError()
def _consumeUntil_type(self,tokenType):
while self.LA(1) != EOF_TYPE and self.LA(1) != tokenType:
self.consume()
def _consumeUntil_bitset(self, set):
while self.LA(1) != EOF_TYPE and not set.member(self.LA(1)):
self.consume()
def consumeUntil(self,arg):
if isinstance(arg,int):
self._consumeUntil_type(arg)
else:
self._consumeUntil_bitset(arg)
def defaultDebuggingSetup(self):
pass
def getAST(self) :
return self.returnAST
def getASTFactory(self) :
return self.astFactory
def getFilename(self) :
return self.inputState.filename
def getInputState(self) :
return self.inputState
def setInputState(self, state) :
self.inputState = state
def getTokenName(self,num) :
return self.tokenNames[num]
def getTokenNames(self) :
return self.tokenNames
def isDebugMode(self) :
return self.false
def LA(self, i):
raise NotImplementedError()
def LT(self, i):
raise NotImplementedError()
def mark(self):
return self.inputState.input.mark()
def _match_int(self,t):
if (self.LA(1) != t):
raise MismatchedTokenException(
self.tokenNames, self.LT(1), t, False, self.getFilename())
else:
self.consume()
def _match_set(self, b):
if (not b.member(self.LA(1))):
raise MismatchedTokenException(
self.tokenNames,self.LT(1), b, False, self.getFilename())
else:
self.consume()
def match(self,set) :
if isinstance(set,int):
self._match_int(set)
return
if isinstance(set,BitSet):
self._match_set(set)
return
raise TypeError("Parser.match requires integer ot BitSet argument")
def matchNot(self,t):
if self.LA(1) == t:
raise MismatchedTokenException(
tokenNames, self.LT(1), t, True, self.getFilename())
else:
self.consume()
def removeMessageListener(self, l) :
if (not self.ignoreInvalidDebugCalls):
runtime_ex(removeMessageListener)
def removeParserListener(self, l) :
if (not self.ignoreInvalidDebugCalls):
runtime_ex(removeParserListener)
def removeParserMatchListener(self, l) :
if (not self.ignoreInvalidDebugCalls):
runtime_ex(removeParserMatchListener)
def removeParserTokenListener(self, l) :
if (not self.ignoreInvalidDebugCalls):
runtime_ex(removeParserTokenListener)
def removeSemanticPredicateListener(self, l) :
if (not self.ignoreInvalidDebugCalls):
runtime_ex(removeSemanticPredicateListener)
def removeSyntacticPredicateListener(self, l) :
if (not self.ignoreInvalidDebugCalls):
runtime_ex(removeSyntacticPredicateListener)
def removeTraceListener(self, l) :
if (not self.ignoreInvalidDebugCalls):
runtime_ex(removeTraceListener)
def reportError(self,x) :
fmt = "syntax error:"
f = self.getFilename()
if f:
fmt = ("%s:" % f) + fmt
if isinstance(x,Token):
line = x.getColumn()
col = x.getLine()
text = x.getText()
fmt = fmt + 'unexpected symbol at line %s (column %s) : "%s"'
print >>sys.stderr, fmt % (line,col,text)
else:
print >>sys.stderr, fmt,str(x)
def reportWarning(self,s):
f = self.getFilename()
if f:
print "%s:warning: %s" % (f,str(x))
else:
print "warning: %s" % (str(x))
def rewind(self, pos) :
self.inputState.input.rewind(pos)
def setASTFactory(self, f) :
self.astFactory = f
def setASTNodeClass(self, cl) :
self.astFactory.setASTNodeType(cl)
def setASTNodeType(self, nodeType) :
self.setASTNodeClass(nodeType)
def setDebugMode(self, debugMode) :
if (not self.ignoreInvalidDebugCalls):
runtime_ex(setDebugMode)
def setFilename(self, f) :
self.inputState.filename = f
def setIgnoreInvalidDebugCalls(self, value) :
self.ignoreInvalidDebugCalls = value
def setTokenBuffer(self, t) :
self.inputState.input = t
def traceIndent(self):
print " " * self.traceDepth
def traceIn(self,rname):
self.traceDepth += 1
self.trace("> ", rname)
def traceOut(self,rname):
self.trace("< ", rname)
self.traceDepth -= 1
### wh: moved from ASTFactory to Parser
def addASTChild(self,currentAST, child):
if not child:
return
if not currentAST.root:
currentAST.root = child
elif not currentAST.child:
currentAST.root.setFirstChild(child)
else:
currentAST.child.setNextSibling(child)
currentAST.child = child
currentAST.advanceChildToEnd()
### wh: moved from ASTFactory to Parser
def makeASTRoot(self,currentAST,root) :
if root:
### Add the current root as a child of new root
root.addChild(currentAST.root)
### The new current child is the last sibling of the old root
currentAST.child = currentAST.root
currentAST.advanceChildToEnd()
### Set the new root
currentAST.root = root
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### LLkParser ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class LLkParser(Parser):
def __init__(self, *args, **kwargs):
try:
arg1 = args[0]
except:
arg1 = 1
if isinstance(arg1,int):
super(LLkParser,self).__init__()
self.k = arg1
return
if isinstance(arg1,ParserSharedInputState):
super(LLkParser,self).__init__(arg1)
self.set_k(1,*args)
return
if isinstance(arg1,TokenBuffer):
super(LLkParser,self).__init__()
self.setTokenBuffer(arg1)
self.set_k(1,*args)
return
if isinstance(arg1,TokenStream):
super(LLkParser,self).__init__()
tokenBuf = TokenBuffer(arg1)
self.setTokenBuffer(tokenBuf)
self.set_k(1,*args)
return
### unknown argument
raise TypeError("LLkParser requires integer, " +
"ParserSharedInputStream or TokenStream argument")
def consume(self):
self.inputState.input.consume()
def LA(self,i):
return self.inputState.input.LA(i)
def LT(self,i):
return self.inputState.input.LT(i)
def set_k(self,index,*args):
try:
self.k = args[index]
except:
self.k = 1
def trace(self,ee,rname):
print type(self)
self.traceIndent()
guess = ""
if self.inputState.guessing > 0:
guess = " [guessing]"
print(ee + rname + guess)
for i in xrange(1,self.k+1):
if i != 1:
print(", ")
if self.LT(i) :
v = self.LT(i).getText()
else:
v = "null"
print "LA(%s) == %s" % (i,v)
print("\n")
def traceIn(self,rname):
self.traceDepth += 1;
self.trace("> ", rname);
def traceOut(self,rname):
self.trace("< ", rname);
self.traceDepth -= 1;
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### TreeParserSharedInputState ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class TreeParserSharedInputState(object):
def __init__(self):
self.guessing = 0
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### TreeParser ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class TreeParser(object):
def __init__(self, *args, **kwargs):
self.inputState = TreeParserSharedInputState()
self._retTree = None
self.tokenNames = []
self.returnAST = None
self.astFactory = ASTFactory()
self.traceDepth = 0
def getAST(self):
return self.returnAST
def getASTFactory(self):
return self.astFactory
def getTokenName(self,num) :
return self.tokenNames[num]
def getTokenNames(self):
return self.tokenNames
def match(self,t,set) :
assert isinstance(set,int) or isinstance(set,BitSet)
if not t or t == ASTNULL:
raise MismatchedTokenException(self.getTokenNames(), t,set, False)
if isinstance(set,int) and t.getType() != set:
raise MismatchedTokenException(self.getTokenNames(), t,set, False)
if isinstance(set,BitSet) and not set.member(t.getType):
raise MismatchedTokenException(self.getTokenNames(), t,set, False)
def matchNot(self,t, ttype) :
if not t or (t == ASTNULL) or (t.getType() == ttype):
raise MismatchedTokenException(getTokenNames(), t, ttype, True)
def reportError(self,ex):
print >>sys.stderr,"error:",ex
def reportWarning(self, s):
print "warning:",s
def setASTFactory(self,f):
self.astFactory = f
def setASTNodeType(self,nodeType):
self.setASTNodeClass(nodeType)
def setASTNodeClass(self,nodeType):
self.astFactory.setASTNodeType(nodeType)
def traceIndent(self):
print " " * self.traceDepth
def traceIn(self,rname,t):
self.traceDepth += 1
self.traceIndent()
print("> " + rname + "(" +
ifelse(t,str(t),"null") + ")" +
ifelse(self.inputState.guessing>0,"[guessing]",""))
def traceOut(self,rname,t):
self.traceIndent()
print("< " + rname + "(" +
ifelse(t,str(t),"null") + ")" +
ifelse(self.inputState.guessing>0,"[guessing]",""))
self.traceDepth -= 1
### wh: moved from ASTFactory to TreeParser
def addASTChild(self,currentAST, child):
if not child:
return
if not currentAST.root:
currentAST.root = child
elif not currentAST.child:
currentAST.root.setFirstChild(child)
else:
currentAST.child.setNextSibling(child)
currentAST.child = child
currentAST.advanceChildToEnd()
### wh: moved from ASTFactory to TreeParser
def makeASTRoot(self,currentAST,root):
if root:
### Add the current root as a child of new root
root.addChild(currentAST.root)
### The new current child is the last sibling of the old root
currentAST.child = currentAST.root
currentAST.advanceChildToEnd()
### Set the new root
currentAST.root = root
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### funcs to work on trees ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
def rightmost(ast):
if ast:
while(ast.right):
ast = ast.right
return ast
def cmptree(s,t,partial):
while(s and t):
### as a quick optimization, check roots first.
if not s.equals(t):
return False
### if roots match, do full list match test on children.
if not cmptree(s.getFirstChild(),t.getFirstChild(),partial):
return False
s = s.getNextSibling()
t = t.getNextSibling()
r = ifelse(partial,not t,not s and not t)
return r
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### AST ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class AST(object):
def __init__(self):
pass
def addChild(self, c):
pass
def equals(self, t):
return False
def equalsList(self, t):
return False
def equalsListPartial(self, t):
return False
def equalsTree(self, t):
return False
def equalsTreePartial(self, t):
return False
def findAll(self, tree):
return None
def findAllPartial(self, subtree):
return None
def getFirstChild(self):
return self
def getNextSibling(self):
return self
def getText(self):
return ""
def getType(self):
return INVALID_TYPE
def getLine(self):
return 0
def getColumn(self):
return 0
def getNumberOfChildren(self):
return 0
def initialize(self, t, txt):
pass
def initialize(self, t):
pass
def setFirstChild(self, c):
pass
def setNextSibling(self, n):
pass
def setText(self, text):
pass
def setType(self, ttype):
pass
def toString(self):
self.getText()
__str__ = toString
def toStringList(self):
return self.getText()
def toStringTree(self):
return self.getText()
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### ASTNULLType ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### There is only one instance of this class **/
class ASTNULLType(AST):
def __init__(self):
AST.__init__(self)
pass
def getText(self):
return "<ASTNULL>"
def getType(self):
return NULL_TREE_LOOKAHEAD
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### BaseAST ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class BaseAST(AST):
verboseStringConversion = False
tokenNames = None
def __init__(self):
self.down = None ## kid
self.right = None ## sibling
def addChild(self,node):
if node:
t = rightmost(self.down)
if t:
t.right = node
else:
assert not self.down
self.down = node
def getNumberOfChildren(self):
t = self.down
n = 0
while t:
n += 1
t = t.right
return n
def doWorkForFindAll(self,v,target,partialMatch):
sibling = self
while sibling:
c1 = partialMatch and sibling.equalsTreePartial(target)
if c1:
v.append(sibling)
else:
c2 = not partialMatch and sibling.equalsTree(target)
if c2:
v.append(sibling)
### regardless of match or not, check any children for matches
if sibling.getFirstChild():
sibling.getFirstChild().doWorkForFindAll(v,target,partialMatch)
sibling = sibling.getNextSibling()
### Is node t equal to 'self' in terms of token type and text?
def equals(self,t):
if not t:
return False
return self.getText() == t.getText() and self.getType() == t.getType()
### Is t an exact structural and equals() match of this tree. The
### 'self' reference is considered the start of a sibling list.
###
def equalsList(self, t):
return cmptree(self, t, partial=False)
### Is 't' a subtree of this list?
### The siblings of the root are NOT ignored.
###
def equalsListPartial(self,t):
return cmptree(self,t,partial=True)
### Is tree rooted at 'self' equal to 't'? The siblings
### of 'self' are ignored.
###
def equalsTree(self, t):
return self.equals(t) and \
cmptree(self.getFirstChild(), t.getFirstChild(), partial=False)
### Is 't' a subtree of the tree rooted at 'self'? The siblings
### of 'self' are ignored.
###
def equalsTreePartial(self, t):
if not t:
return True
return self.equals(t) and cmptree(
self.getFirstChild(), t.getFirstChild(), partial=True)
### Walk the tree looking for all exact subtree matches. Return
### an ASTEnumerator that lets the caller walk the list
### of subtree roots found herein.
def findAll(self,target):
roots = []
### the empty tree cannot result in an enumeration
if not target:
return None
# find all matches recursively
self.doWorkForFindAll(roots, target, False)
return roots
### Walk the tree looking for all subtrees. Return
### an ASTEnumerator that lets the caller walk the list
### of subtree roots found herein.
def findAllPartial(self,sub):
roots = []
### the empty tree cannot result in an enumeration
if not sub:
return None
self.doWorkForFindAll(roots, sub, True) ### find all matches recursively
return roots
### Get the first child of this node None if not children
def getFirstChild(self):
return self.down
### Get the next sibling in line after this one
def getNextSibling(self):
return self.right
### Get the token text for this node
def getText(self):
return ""
### Get the token type for this node
def getType(self):
return 0
def getLine(self):
return 0
def getColumn(self):
return 0
### Remove all children */
def removeChildren(self):
self.down = None
def setFirstChild(self,c):
self.down = c
def setNextSibling(self, n):
self.right = n
### Set the token text for this node
def setText(self, text):
pass
### Set the token type for this node
def setType(self, ttype):
pass
### static
def setVerboseStringConversion(verbose,names):
verboseStringConversion = verbose
tokenNames = names
setVerboseStringConversion = staticmethod(setVerboseStringConversion)
### Return an array of strings that maps token ID to it's text.
## @since 2.7.3
def getTokenNames():
return tokenNames
def toString(self):
return self.getText()
### return tree as lisp string - sibling included
def toStringList(self):
ts = self.toStringTree()
sib = self.getNextSibling()
if sib:
ts += sib.toStringList()
return ts
__str__ = toStringList
### return tree as string - siblings ignored
def toStringTree(self):
ts = ""
kid = self.getFirstChild()
if kid:
ts += " ("
ts += " " + self.toString()
if kid:
ts += kid.toStringList()
ts += " )"
return ts
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### CommonAST ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### Common AST node implementation
class CommonAST(BaseAST):
def __init__(self,token=None):
super(CommonAST,self).__init__()
self.ttype = INVALID_TYPE
self.text = "<no text>"
self.initialize(token)
#assert self.text
### Get the token text for this node
def getText(self):
return self.text
### Get the token type for this node
def getType(self):
return self.ttype
def initialize(self,*args):
if not args:
return
arg0 = args[0]
if isinstance(arg0,int):
arg1 = args[1]
self.setType(arg0)
self.setText(arg1)
return
if isinstance(arg0,AST) or isinstance(arg0,Token):
self.setText(arg0.getText())
self.setType(arg0.getType())
return
### Set the token text for this node
def setText(self,text_):
assert isinstance(text_,str)
self.text = text_
### Set the token type for this node
def setType(self,ttype_):
assert isinstance(ttype_,int)
self.ttype = ttype_
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### CommonASTWithHiddenTokens ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class CommonASTWithHiddenTokens(CommonAST):
def __init__(self,*args):
CommonAST.__init__(self,*args)
self.hiddenBefore = None
self.hiddenAfter = None
def getHiddenAfter(self):
return self.hiddenAfter
def getHiddenBefore(self):
return self.hiddenBefore
def initialize(self,*args):
CommonAST.initialize(self,*args)
if args and isinstance(args[0],Token):
assert isinstance(args[0],CommonHiddenStreamToken)
self.hideenBefore = args[0].getHiddenBefore()
self.hiddenAfter = args[0].getHiddenAfter()
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### ASTPair ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class ASTPair(object):
def __init__(self):
self.root = None ### current root of tree
self.child = None ### current child to which siblings are added
### Make sure that child is the last sibling */
def advanceChildToEnd(self):
if self.child:
while self.child.getNextSibling():
self.child = self.child.getNextSibling()
### Copy an ASTPair. Don't call it clone() because we want type-safety */
def copy(self):
tmp = ASTPair()
tmp.root = self.root
tmp.child = self.child
return tmp
def toString(self):
r = ifelse(not root,"null",self.root.getText())
c = ifelse(not child,"null",self.child.getText())
return "[%s,%s]" % (r,c)
__str__ = toString
__repr__ = toString
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### ASTFactory ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class ASTFactory(object):
def __init__(self,table=None):
self._class = None
self._classmap = ifelse(table,table,None)
def create(self,*args):
if not args:
return self.create(INVALID_TYPE)
arg0 = args[0]
arg1 = None
arg2 = None
try:
arg1 = args[1]
arg2 = args[2]
except:
pass
# ctor(int)
if isinstance(arg0,int) and not arg2:
### get class for 'self' type
c = self.getASTNodeType(arg0)
t = self.create(c)
if t:
t.initialize(arg0, ifelse(arg1,arg1,""))
return t
# ctor(int,something)
if isinstance(arg0,int) and arg2:
t = self.create(arg2)
if t:
t.initialize(arg0,arg1)
return t
# ctor(AST)
if isinstance(arg0,AST):
t = self.create(arg0.getType())
if t:
t.initialize(arg0)
return t
# ctor(token)
if isinstance(arg0,Token) and not arg1:
ttype = arg0.getType()
assert isinstance(ttype,int)
t = self.create(ttype)
if t:
t.initialize(arg0)
return t
# ctor(token,class)
if isinstance(arg0,Token) and arg1:
assert isinstance(arg1,type)
assert issubclass(arg1,AST)
# this creates instance of 'arg1' using 'arg0' as
# argument. Wow, that's magic!
t = arg1(arg0)
assert t and isinstance(t,AST)
return t
# ctor(class)
if isinstance(arg0,type):
### next statement creates instance of type (!)
t = arg0()
assert isinstance(t,AST)
return t
def setASTNodeClass(self,className=None):
if not className:
return
assert isinstance(className,type)
assert issubclass(className,AST)
self._class = className
### kind of misnomer - use setASTNodeClass instead.
setASTNodeType = setASTNodeClass
def getASTNodeClass(self):
return self._class
def getTokenTypeToASTClassMap(self):
return self._classmap
def setTokenTypeToASTClassMap(self,amap):
self._classmap = amap
def error(self, e):
import sys
print >> sys.stderr, e
def setTokenTypeASTNodeType(self, tokenType, className):
"""
Specify a mapping between a token type and a (AST) class.
"""
if not self._classmap:
self._classmap = {}
if not className:
try:
del self._classmap[tokenType]
except:
pass
else:
### here we should also perform actions to ensure that
### a. class can be loaded
### b. class is a subclass of AST
###
assert isinstance(className,type)
assert issubclass(className,AST) ## a & b
### enter the class
self._classmap[tokenType] = className
def getASTNodeType(self,tokenType):
"""
For a given token type return the AST node type. First we
lookup a mapping table, second we try _class
and finally we resolve to "antlr.CommonAST".
"""
# first
if self._classmap:
try:
c = self._classmap[tokenType]
if c:
return c
except:
pass
# second
if self._class:
return self._class
# default
return CommonAST
### methods that have been moved to file scope - just listed
### here to be somewhat consistent with original API
def dup(self,t):
return antlr.dup(t,self)
def dupList(self,t):
return antlr.dupList(t,self)
def dupTree(self,t):
return antlr.dupTree(t,self)
### methods moved to other classes
### 1. makeASTRoot -> Parser
### 2. addASTChild -> Parser
### non-standard: create alias for longish method name
maptype = setTokenTypeASTNodeType
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### ASTVisitor ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
class ASTVisitor(object):
def __init__(self,*args):
pass
def visit(self,ast):
pass
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
### static methods and variables ###
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
ASTNULL = ASTNULLType()
### wh: moved from ASTFactory as there's nothing ASTFactory-specific
### in this method.
def make(*nodes):
if not nodes:
return None
for i in xrange(0,len(nodes)):
node = nodes[i]
if node:
assert isinstance(node,AST)
root = nodes[0]
tail = None
if root:
root.setFirstChild(None)
for i in xrange(1,len(nodes)):
if not nodes[i]:
continue
if not root:
root = tail = nodes[i]
elif not tail:
root.setFirstChild(nodes[i])
tail = root.getFirstChild()
else:
tail.setNextSibling(nodes[i])
tail = tail.getNextSibling()
### Chase tail to last sibling
while tail.getNextSibling():
tail = tail.getNextSibling()
return root
def dup(t,factory):
if not t:
return None
if factory:
dup_t = factory.create(t.__class__)
else:
raise TypeError("dup function requires ASTFactory argument")
dup_t.initialize(t)
return dup_t
def dupList(t,factory):
result = dupTree(t,factory)
nt = result
while t:
## for each sibling of the root
t = t.getNextSibling()
nt.setNextSibling(dupTree(t,factory))
nt = nt.getNextSibling()
return result
def dupTree(t,factory):
result = dup(t,factory)
if t:
result.setFirstChild(dupList(t.getFirstChild(),factory))
return result
###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
### $Id: antlr.py,v 1.2 2005/10/26 07:44:24 rvk Exp $
# Local Variables: ***
# mode: python ***
# py-indent-offset: 4 ***
# End: ***