home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyc (Python 2.6) ''' pyparsing module - Classes and methods to define and execute parsing grammars The pyparsing module is an alternative approach to creating and executing simple grammars, vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you don\'t need to learn a new syntax for defining grammars or matching expressions - the parsing module provides a library of classes that you use to construct the grammar directly in Python. Here is a program to parse "Hello, World!" (or any greeting of the form "<salutation>, <addressee>!"):: from pyparsing import Word, alphas # define grammar of a greeting greet = Word( alphas ) + "," + Word( alphas ) + "!" hello = "Hello, World!" print hello, "->", greet.parseString( hello ) The program outputs the following:: Hello, World! -> [\'Hello\', \',\', \'World\', \'!\'] The Python representation of the grammar is quite readable, owing to the self-explanatory class names, and the use of \'+\', \'|\' and \'^\' operators. The parsed results returned from parseString() can be accessed as a nested list, a dictionary, or an object with named attributes. The pyparsing module handles some of the problems that are typically vexing when writing text parsers: - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) - quoted strings - embedded comments ''' __version__ = '1.5.1' __versionTime__ = '2 October 2008 00:44' __author__ = 'Paul McGuire <ptmcg@users.sourceforge.net>' import string from weakref import ref as wkref import copy import sys import warnings import re import sre_constants __all__ = [ 'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', 'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', 'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', 'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', 'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', 'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', 'Upcase', 'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', 'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', 'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', 'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'getTokensEndLoc', 'hexnums', 'htmlComment', 'javaStyleComment', 'keepOriginalText', 'line', 'lineEnd', 'lineStart', 'lineno', 'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', 'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', 'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', 'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', 'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', 'indentedBlock', 'originalTextFor'] if sys.version_info[0] > 2: _PY3K = True _MAX_INT = sys.maxsize basestring = str else: _PY3K = False _MAX_INT = sys.maxint if not _PY3K: def _ustr(obj): try: return str(obj) except UnicodeEncodeError: return unicode(obj) else: _ustr = str unichr = chr def _str2dict(strg): return []([ (c, 0) for c in strg ]) def _xml_escape(data): from_symbols = '&><"\'' to_symbols = [ '&' + s + ';' for s in 'amp gt lt quot apos'.split() ] for from_, to_ in zip(from_symbols, to_symbols): data = data.replace(from_, to_) return data class _Constants(object): pass if not _PY3K: alphas = string.lowercase + string.uppercase else: alphas = string.ascii_lowercase + string.ascii_uppercase nums = string.digits hexnums = nums + 'ABCDEFabcdef' alphanums = alphas + nums _bslash = chr(92) printables = []([] if c not in string.whitespace else _[1]) class ParseBaseException(Exception): __slots__ = ('loc', 'msg', 'pstr', 'parserElement') def __init__(self, pstr, loc = 0, msg = None, elem = None): self.loc = loc if msg is None: self.msg = pstr self.pstr = '' else: self.msg = msg self.pstr = pstr self.parserElement = elem def __getattr__(self, aname): if aname == 'lineno': return lineno(self.loc, self.pstr) if aname in ('col', 'column'): return col(self.loc, self.pstr) if aname == 'line': return line(self.loc, self.pstr) raise AttributeError(aname) def __str__(self): return '%s (at char %d), (line:%d, col:%d)' % (self.msg, self.loc, self.lineno, self.column) def __repr__(self): return _ustr(self) def markInputline(self, markerString = '>!<'): line_str = self.line line_column = self.column - 1 if markerString: line_str = ''.join([ line_str[:line_column], markerString, line_str[line_column:]]) return line_str.strip() def __dir__(self): return 'loc msg pstr parserElement lineno col line markInputLine __str__ __repr__'.split() class ParseException(ParseBaseException): pass class ParseFatalException(ParseBaseException): pass class ParseSyntaxException(ParseFatalException): def __init__(self, pe): super(ParseSyntaxException, self).__init__(pe.pstr, pe.loc, pe.msg, pe.parserElement) class RecursiveGrammarException(Exception): def __init__(self, parseElementList): self.parseElementTrace = parseElementList def __str__(self): return 'RecursiveGrammarException: %s' % self.parseElementTrace class _ParseResultsWithOffset(object): def __init__(self, p1, p2): self.tup = (p1, p2) def __getitem__(self, i): return self.tup[i] def __repr__(self): return repr(self.tup) def setOffset(self, i): self.tup = (self.tup[0], i) class ParseResults(object): __slots__ = ('__toklist', '__tokdict', '__doinit', '__name', '__parent', '__accumNames', '__weakref__') def __new__(cls, toklist, name = None, asList = True, modal = True): if isinstance(toklist, cls): return toklist retobj = object.__new__(cls) retobj._ParseResults__doinit = True return retobj def __init__(self, toklist, name = None, asList = True, modal = True): if self._ParseResults__doinit: self._ParseResults__doinit = False self._ParseResults__name = None self._ParseResults__parent = None self._ParseResults__accumNames = { } if isinstance(toklist, list): self._ParseResults__toklist = toklist[:] else: self._ParseResults__toklist = [ toklist] self._ParseResults__tokdict = dict() if name: if not modal: self._ParseResults__accumNames[name] = 0 if isinstance(name, int): name = _ustr(name) self._ParseResults__name = name if toklist not in (None, '', []): if isinstance(toklist, basestring): toklist = [ toklist] None if asList else None<EXCEPTION MATCH>(KeyError, TypeError) def __getitem__(self, i): if isinstance(i, (int, slice)): return self._ParseResults__toklist[i] if i not in self._ParseResults__accumNames: return self._ParseResults__tokdict[i][-1][0] return []([ v[0] for v in self._ParseResults__tokdict[i] ]) def __setitem__(self, k, v): if isinstance(v, _ParseResultsWithOffset): self._ParseResults__tokdict[k] = self._ParseResults__tokdict.get(k, list()) + [ v] sub = v[0] elif isinstance(k, int): self._ParseResults__toklist[k] = v sub = v else: self._ParseResults__tokdict[k] = self._ParseResults__tokdict.get(k, list()) + [ _ParseResultsWithOffset(v, 0)] sub = v if isinstance(sub, ParseResults): sub._ParseResults__parent = wkref(self) def __delitem__(self, i): if isinstance(i, (int, slice)): mylen = len(self._ParseResults__toklist) del self._ParseResults__toklist[i] if isinstance(i, int): if i < 0: i += mylen i = slice(i, i + 1) removed = list(range(*i.indices(mylen))) removed.reverse() for name in self._ParseResults__tokdict: occurrences = self._ParseResults__tokdict[name] for j in removed: for value, position in enumerate(occurrences): occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) else: del self._ParseResults__tokdict[i] def __contains__(self, k): return k in self._ParseResults__tokdict def __len__(self): return len(self._ParseResults__toklist) def __bool__(self): return len(self._ParseResults__toklist) > 0 __nonzero__ = __bool__ def __iter__(self): return iter(self._ParseResults__toklist) def __reversed__(self): return iter(reversed(self._ParseResults__toklist)) def keys(self): return self._ParseResults__tokdict.keys() def pop(self, index = -1): ret = self[index] del self[index] return ret def get(self, key, defaultValue = None): if key in self: return self[key] return defaultValue def insert(self, index, insStr): self._ParseResults__toklist.insert(index, insStr) for name in self._ParseResults__tokdict: occurrences = self._ParseResults__tokdict[name] for value, position in enumerate(occurrences): occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) def items(self): return [ (k, self[k]) for k in self._ParseResults__tokdict ] def values(self): return [ v[-1][0] for v in self._ParseResults__tokdict.values() ] def __getattr__(self, name): if name not in self.__slots__: if name in self._ParseResults__tokdict: if name not in self._ParseResults__accumNames: return self._ParseResults__tokdict[name][-1][0] return []([ v[0] for v in self._ParseResults__tokdict[name] ]) name in self._ParseResults__tokdict return '' name not in self.__slots__ def __add__(self, other): ret = self.copy() ret += other return ret def __iadd__(self, other): self._ParseResults__toklist += other._ParseResults__toklist self._ParseResults__accumNames.update(other._ParseResults__accumNames) del other return self def __repr__(self): return '(%s, %s)' % (repr(self._ParseResults__toklist), repr(self._ParseResults__tokdict)) def __str__(self): out = '[' sep = '' for i in self._ParseResults__toklist: if isinstance(i, ParseResults): out += sep + _ustr(i) else: out += sep + repr(i) sep = ', ' out += ']' return out def _asStringList(self, sep = ''): out = [] for item in self._ParseResults__toklist: if out and sep: out.append(sep) if isinstance(item, ParseResults): out += item._asStringList() continue out.append(_ustr(item)) return out def asList(self): out = [] for res in self._ParseResults__toklist: if isinstance(res, ParseResults): out.append(res.asList()) continue out.append(res) return out def asDict(self): return dict(self.items()) def copy(self): ret = ParseResults(self._ParseResults__toklist) ret._ParseResults__tokdict = self._ParseResults__tokdict.copy() ret._ParseResults__parent = self._ParseResults__parent ret._ParseResults__accumNames.update(self._ParseResults__accumNames) ret._ParseResults__name = self._ParseResults__name return ret def asXML(self, doctag = None, namedItemsOnly = False, indent = '', formatted = True): nl = '\n' out = [] namedItems = []([ (v[1], k) for k, vlist in self._ParseResults__tokdict.items() for v in vlist ]) nextLevelIndent = indent + ' ' selfTag = None if doctag is not None: selfTag = doctag elif self._ParseResults__name: selfTag = self._ParseResults__name if not selfTag: if namedItemsOnly: return '' selfTag = 'ITEM' out += [ nl, indent, '<', selfTag, '>'] worklist = self._ParseResults__toklist for i, res in enumerate(worklist): if isinstance(res, ParseResults): if i in namedItems: if namedItemsOnly: pass out += [ res.asXML(namedItems[i], doctag is None, nextLevelIndent, formatted)] elif namedItemsOnly: pass out += [ res.asXML(None, doctag is None, nextLevelIndent, formatted)] continue resTag = None if i in namedItems: resTag = namedItems[i] if not resTag: if namedItemsOnly: continue else: resTag = 'ITEM' xmlBodyText = _xml_escape(_ustr(res)) out += [ nl, nextLevelIndent, '<', resTag, '>', xmlBodyText, '</', resTag, '>'] out += [ nl, indent, '</', selfTag, '>'] return ''.join(out) def __lookup(self, sub): for k, vlist in self._ParseResults__tokdict.items(): for v, loc in vlist: if sub is v: return k def getName(self): if self._ParseResults__name: return self._ParseResults__name if self._ParseResults__parent: par = self._ParseResults__parent() if par: return par._ParseResults__lookup(self) return None self._ParseResults__parent if len(self) == 1 and len(self._ParseResults__tokdict) == 1 and self._ParseResults__tokdict.values()[0][0][1] in (0, -1): return self._ParseResults__tokdict.keys()[0] return None def dump(self, indent = '', depth = 0): out = [] out.append(indent + _ustr(self.asList())) keys = self.items() keys.sort() for k, v in keys: if out: out.append('\n') out.append('%s%s- %s: ' % (indent, ' ' * depth, k)) if isinstance(v, ParseResults): if v.keys(): out.append(v.dump(indent, depth + 1)) else: out.append(_ustr(v)) v.keys() out.append(_ustr(v)) return ''.join(out) def __getstate__(self): if not self._ParseResults__parent is not None or self._ParseResults__parent(): pass return (self._ParseResults__toklist, (self._ParseResults__tokdict.copy(), None, self._ParseResults__accumNames, self._ParseResults__name)) def __setstate__(self, state): self._ParseResults__toklist = state[0] (self._ParseResults__tokdict, par, inAccumNames, self._ParseResults__name) = state[1] self._ParseResults__accumNames = { } self._ParseResults__accumNames.update(inAccumNames) if par is not None: self._ParseResults__parent = wkref(par) else: self._ParseResults__parent = None def __dir__(self): return dir(super(ParseResults, self)) + self.keys() def col(loc, strg): if not loc < len(strg) or strg[loc] == '\n' or 1: pass return loc - strg.rfind('\n', 0, loc) def lineno(loc, strg): return strg.count('\n', 0, loc) + 1 def line(loc, strg): lastCR = strg.rfind('\n', 0, loc) nextCR = strg.find('\n', loc) if nextCR > 0: return strg[lastCR + 1:nextCR] return strg[lastCR + 1:] def _defaultStartDebugAction(instring, loc, expr): print 'Match ' + _ustr(expr) + ' at loc ' + _ustr(loc) + '(%d,%d)' % (lineno(loc, instring), col(loc, instring)) def _defaultSuccessDebugAction(instring, startloc, endloc, expr, toks): print 'Matched ' + _ustr(expr) + ' -> ' + str(toks.asList()) def _defaultExceptionDebugAction(instring, loc, expr, exc): print 'Exception raised:' + _ustr(exc) def nullDebugAction(*args): pass class ParserElement(object): DEFAULT_WHITE_CHARS = ' \n\t\r' def setDefaultWhitespaceChars(chars): ParserElement.DEFAULT_WHITE_CHARS = chars setDefaultWhitespaceChars = staticmethod(setDefaultWhitespaceChars) def __init__(self, savelist = False): self.parseAction = list() self.failAction = None self.strRepr = None self.resultsName = None self.saveAsList = savelist self.skipWhitespace = True self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS self.copyDefaultWhiteChars = True self.mayReturnEmpty = False self.keepTabs = False self.ignoreExprs = list() self.debug = False self.streamlined = False self.mayIndexError = True self.errmsg = '' self.modalResults = True self.debugActions = (None, None, None) self.re = None self.callPreparse = True self.callDuringTry = False def copy(self): cpy = copy.copy(self) cpy.parseAction = self.parseAction[:] cpy.ignoreExprs = self.ignoreExprs[:] if self.copyDefaultWhiteChars: cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS return cpy def setName(self, name): self.name = name self.errmsg = 'Expected ' + self.name if hasattr(self, 'exception'): self.exception.msg = self.errmsg return self def setResultsName(self, name, listAllMatches = False): newself = self.copy() newself.resultsName = name newself.modalResults = not listAllMatches return newself def setBreak(self, breakFlag = True): if breakFlag: _parseMethod = self._parse def breaker(instring, loc, doActions = True, callPreParse = (True,)): import pdb pdb.set_trace() return _parseMethod(instring, loc, doActions, callPreParse) breaker._originalParseMethod = _parseMethod self._parse = breaker elif hasattr(self._parse, '_originalParseMethod'): self._parse = self._parse._originalParseMethod return self def _normalizeParseActionArgs(f): STAR_ARGS = 4 try: restore = None if isinstance(f, type): restore = f f = f.__init__ if not _PY3K: codeObj = f.func_code else: codeObj = f.code if codeObj.co_flags & STAR_ARGS: return f numargs = codeObj.co_argcount if not _PY3K: if hasattr(f, 'im_self'): numargs -= 1 elif hasattr(f, '__self__'): numargs -= 1 if restore: f = restore except AttributeError: try: if not _PY3K: call_im_func_code = f.__call__.im_func.func_code else: call_im_func_code = f.__code__ if call_im_func_code.co_flags & STAR_ARGS: return f numargs = call_im_func_code.co_argcount if not _PY3K: if hasattr(f.__call__, 'im_self'): numargs -= 1 elif hasattr(f.__call__, '__self__'): numargs -= 0 except AttributeError: if not _PY3K: call_func_code = f.__call__.func_code else: call_func_code = f.__call__.__code__ if call_func_code.co_flags & STAR_ARGS: return f numargs = call_func_code.co_argcount if not _PY3K: if hasattr(f.__call__, 'im_self'): numargs -= 1 elif hasattr(f.__call__, '__self__'): numargs -= 1 except: _PY3K call_func_code.co_flags & STAR_ARGS if numargs == 3: return f if numargs > 3: def tmp(s, l, t): return f(f.__call__.__self__, s, l, t) if numargs == 2: def tmp(s, l, t): return f(l, t) elif numargs == 1: def tmp(s, l, t): return f(t) else: def tmp(s, l, t): return f() try: tmp.__name__ = f.__name__ except (AttributeError, TypeError): (None,) (None,) except: (None,) try: tmp.__doc__ = f.__doc__ except (AttributeError, TypeError): (None,) (None,) except: (None,) try: tmp.__dict__.update(f.__dict__) except (AttributeError, TypeError): (None,) (None,) except: (None,) return tmp _normalizeParseActionArgs = staticmethod(_normalizeParseActionArgs) def setParseAction(self, *fns, **kwargs): self.parseAction = list(map(self._normalizeParseActionArgs, list(fns))) if 'callDuringTry' in kwargs: pass self.callDuringTry = kwargs['callDuringTry'] return self def addParseAction(self, *fns, **kwargs): self.parseAction += list(map(self._normalizeParseActionArgs, list(fns))) if self.callDuringTry and 'callDuringTry' in kwargs: pass self.callDuringTry = kwargs['callDuringTry'] return self def setFailAction(self, fn): self.failAction = fn return self def _skipIgnorables(self, instring, loc): exprsFound = True while exprsFound: exprsFound = False for e in self.ignoreExprs: try: while None: (loc, dummy) = e._parse(instring, loc) exprsFound = True continue except ParseException: continue continue return loc def preParse(self, instring, loc): if self.ignoreExprs: loc = self._skipIgnorables(instring, loc) if self.skipWhitespace: wt = self.whiteChars instrlen = len(instring) while loc < instrlen and instring[loc] in wt: loc += 1 return loc def parseImpl(self, instring, loc, doActions = True): return (loc, []) def postParse(self, instring, loc, tokenlist): return tokenlist def _parseNoCache(self, instring, loc, doActions = True, callPreParse = True): debugging = self.debug if debugging or self.failAction: if self.debugActions[0]: self.debugActions[0](instring, loc, self) if callPreParse and self.callPreparse: preloc = self.preParse(instring, loc) else: preloc = loc tokensStart = loc try: try: (loc, tokens) = self.parseImpl(instring, preloc, doActions) except IndexError: raise ParseException(instring, len(instring), self.errmsg, self) except ParseBaseException: err = None if self.debugActions[2]: self.debugActions[2](instring, tokensStart, self, err) if self.failAction: self.failAction(instring, tokensStart, self, err) raise except: None<EXCEPTION MATCH>ParseBaseException None<EXCEPTION MATCH>ParseBaseException if callPreParse and self.callPreparse: preloc = self.preParse(instring, loc) else: preloc = loc tokensStart = loc if self.mayIndexError or loc >= len(instring): try: (loc, tokens) = self.parseImpl(instring, preloc, doActions) except IndexError: raise ParseException(instring, len(instring), self.errmsg, self) except: None<EXCEPTION MATCH>IndexError None<EXCEPTION MATCH>IndexError (loc, tokens) = self.parseImpl(instring, preloc, doActions) tokens = self.postParse(instring, loc, tokens) retTokens = ParseResults(tokens, self.resultsName, asList = self.saveAsList, modal = self.modalResults) if self.parseAction: if doActions or self.callDuringTry: if debugging: try: for fn in self.parseAction: tokens = fn(instring, tokensStart, retTokens) if tokens is not None: if self.saveAsList: pass retTokens = ParseResults(tokens, self.resultsName, asList = isinstance(tokens, (ParseResults, list)), modal = self.modalResults) continue except ParseBaseException: err = None if self.debugActions[2]: self.debugActions[2](instring, tokensStart, self, err) raise except: None<EXCEPTION MATCH>ParseBaseException None<EXCEPTION MATCH>ParseBaseException for fn in self.parseAction: tokens = fn(instring, tokensStart, retTokens) if tokens is not None: if self.saveAsList: pass retTokens = ParseResults(tokens, self.resultsName, asList = isinstance(tokens, (ParseResults, list)), modal = self.modalResults) continue if debugging: if self.debugActions[1]: self.debugActions[1](instring, tokensStart, loc, self, retTokens) return (loc, retTokens) def tryParse(self, instring, loc): try: return self._parse(instring, loc, doActions = False)[0] except ParseFatalException: raise ParseException(instring, loc, self.errmsg, self) def _parseCache(self, instring, loc, doActions = True, callPreParse = True): lookup = (self, instring, loc, callPreParse, doActions) if lookup in ParserElement._exprArgCache: value = ParserElement._exprArgCache[lookup] if isinstance(value, Exception): raise value isinstance(value, Exception) return value try: value = self._parseNoCache(instring, loc, doActions, callPreParse) ParserElement._exprArgCache[lookup] = (value[0], value[1].copy()) return value except ParseBaseException: lookup in ParserElement._exprArgCache pe = lookup in ParserElement._exprArgCache ParserElement._exprArgCache[lookup] = pe raise except: lookup in ParserElement._exprArgCache _parse = _parseNoCache _exprArgCache = { } def resetCache(): ParserElement._exprArgCache.clear() resetCache = staticmethod(resetCache) _packratEnabled = False def enablePackrat(): if not ParserElement._packratEnabled: ParserElement._packratEnabled = True ParserElement._parse = ParserElement._parseCache enablePackrat = staticmethod(enablePackrat) def parseString(self, instring, parseAll = False): ParserElement.resetCache() if not self.streamlined: self.streamline() for e in self.ignoreExprs: e.streamline() if not self.keepTabs: instring = instring.expandtabs() (loc, tokens) = self._parse(instring, 0) if parseAll: loc = self.preParse(instring, loc) StringEnd()._parse(instring, loc) return tokens def scanString(self, instring, maxMatches = _MAX_INT): if not self.streamlined: self.streamline() for e in self.ignoreExprs: e.streamline() if not self.keepTabs: instring = _ustr(instring).expandtabs() instrlen = len(instring) loc = 0 preparseFn = self.preParse parseFn = self._parse ParserElement.resetCache() matches = 0 while loc <= instrlen and matches < maxMatches: try: preloc = preparseFn(instring, loc) (nextLoc, tokens) = parseFn(instring, preloc, callPreParse = False) except ParseException: loc = preloc + 1 continue matches += 1 yield (tokens, preloc, nextLoc) loc = nextLoc def transformString(self, instring): out = [] lastE = 0 self.keepTabs = True for t, s, e in self.scanString(instring): out.append(instring[lastE:s]) if t: if isinstance(t, ParseResults): out += t.asList() elif isinstance(t, list): out += t else: out.append(t) lastE = e out.append(instring[lastE:]) return ''.join(map(_ustr, out)) def searchString(self, instring, maxMatches = _MAX_INT): return []([ t for t, s, e in self.scanString(instring, maxMatches) ]) def __add__(self, other): if isinstance(other, basestring): other = Literal(other) if not isinstance(other, ParserElement): warnings.warn('Cannot combine element of type %s with ParserElement' % type(other), SyntaxWarning, stacklevel = 2) return None return And([ self, other]) def __radd__(self, other): if isinstance(other, basestring): other = Literal(other) if not isinstance(other, ParserElement): warnings.warn('Cannot combine element of type %s with ParserElement' % type(other), SyntaxWarning, stacklevel = 2) return None return other + self def __sub__(self, other): if isinstance(other, basestring): other = Literal(other) if not isinstance(other, ParserElement): warnings.warn('Cannot combine element of type %s with ParserElement' % type(other), SyntaxWarning, stacklevel = 2) return None return And([ self, And._ErrorStop(), other]) def __rsub__(self, other): if isinstance(other, basestring): other = Literal(other) if not isinstance(other, ParserElement): warnings.warn('Cannot combine element of type %s with ParserElement' % type(other), SyntaxWarning, stacklevel = 2) return None return other - self def __mul__(self, other): if isinstance(other, int): minElements = other optElements = 0 elif isinstance(other, tuple): other = other + (None, None)[:2] if other[0] is None: other = (0, other[1]) if isinstance(other[0], int) and other[1] is None: if other[0] == 0: return ZeroOrMore(self) if other[0] == 1: return OneOrMore(self) return self * other[0] + ZeroOrMore(self) other[1] is None if isinstance(other[0], int) and isinstance(other[1], int): (minElements, optElements) = other optElements -= minElements else: raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]), type(other[1])) isinstance(other[1], int) raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) if minElements < 0: raise ValueError('cannot multiply ParserElement by negative value') minElements < 0 if optElements < 0: raise ValueError('second tuple value must be greater or equal to first tuple value') optElements < 0 if optElements == optElements: pass elif optElements == 0: raise ValueError('cannot multiply ParserElement by 0 or (0,0)') if optElements: def makeOptionalList(n): if n > 1: return Optional(self + makeOptionalList(n - 1)) return Optional(self) if minElements: if minElements == 1: ret = self + makeOptionalList(optElements) else: ret = And([ self] * minElements) + makeOptionalList(optElements) else: ret = makeOptionalList(optElements) elif minElements == 1: ret = self else: ret = And([ self] * minElements) return ret def __rmul__(self, other): return self.__mul__(other) def __or__(self, other): if isinstance(other, basestring): other = Literal(other) if not isinstance(other, ParserElement): warnings.warn('Cannot combine element of type %s with ParserElement' % type(other), SyntaxWarning, stacklevel = 2) return None return MatchFirst([ self, other]) def __ror__(self, other): if isinstance(other, basestring): other = Literal(other) if not isinstance(other, ParserElement): warnings.warn('Cannot combine element of type %s with ParserElement' % type(other), SyntaxWarning, stacklevel = 2) return None return other | self def __xor__(self, other): if isinstance(other, basestring): other = Literal(other) if not isinstance(other, ParserElement): warnings.warn('Cannot combine element of type %s with ParserElement' % type(other), SyntaxWarning, stacklevel = 2) return None return Or([ self, other]) def __rxor__(self, other): if isinstance(other, basestring): other = Literal(other) if not isinstance(other, ParserElement): warnings.warn('Cannot combine element of type %s with ParserElement' % type(other), SyntaxWarning, stacklevel = 2) return None return other ^ self def __and__(self, other): if isinstance(other, basestring): other = Literal(other) if not isinstance(other, ParserElement): warnings.warn('Cannot combine element of type %s with ParserElement' % type(other), SyntaxWarning, stacklevel = 2) return None return Each([ self, other]) def __rand__(self, other): if isinstance(other, basestring): other = Literal(other) if not isinstance(other, ParserElement): warnings.warn('Cannot combine element of type %s with ParserElement' % type(other), SyntaxWarning, stacklevel = 2) return None return other & self def __invert__(self): return NotAny(self) def __call__(self, name): return self.setResultsName(name) def suppress(self): return Suppress(self) def leaveWhitespace(self): self.skipWhitespace = False return self def setWhitespaceChars(self, chars): self.skipWhitespace = True self.whiteChars = chars self.copyDefaultWhiteChars = False return self def parseWithTabs(self): self.keepTabs = True return self def ignore(self, other): if isinstance(other, Suppress): if other not in self.ignoreExprs: self.ignoreExprs.append(other) else: self.ignoreExprs.append(Suppress(other)) return self def setDebugActions(self, startAction, successAction, exceptionAction): if not startAction: pass if not successAction: pass if not exceptionAction: pass self.debugActions = (_defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction) self.debug = True return self def setDebug(self, flag = True): if flag: self.setDebugActions(_defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction) else: self.debug = False return self def __str__(self): return self.name def __repr__(self): return _ustr(self) def streamline(self): self.streamlined = True self.strRepr = None return self def checkRecursion(self, parseElementList): pass def validate(self, validateTrace = []): self.checkRecursion([]) def parseFile(self, file_or_filename, parseAll = False): try: file_contents = file_or_filename.read() except AttributeError: f = open(file_or_filename, 'rb') file_contents = f.read() f.close() return self.parseString(file_contents, parseAll) def getException(self): return ParseException('', 0, self.errmsg, self) def __getattr__(self, aname): if aname == 'myException': self.myException = ret = self.getException() return ret raise AttributeError('no such attribute ' + aname) def __eq__(self, other): if isinstance(other, basestring): try: (self + StringEnd()).parseString(_ustr(other)) return True except ParseBaseException: return False None<EXCEPTION MATCH>ParseBaseException return super(ParserElement, self) == other def __ne__(self, other): return not (self == other) def __hash__(self): return hash(id(self)) def __req__(self, other): return self == other def __rne__(self, other): return not (self == other) class Token(ParserElement): def __init__(self): super(Token, self).__init__(savelist = False) def setName(self, name): s = super(Token, self).setName(name) self.errmsg = 'Expected ' + self.name return s class Empty(Token): def __init__(self): super(Empty, self).__init__() self.name = 'Empty' self.mayReturnEmpty = True self.mayIndexError = False class NoMatch(Token): def __init__(self): super(NoMatch, self).__init__() self.name = 'NoMatch' self.mayReturnEmpty = True self.mayIndexError = False self.errmsg = 'Unmatchable token' def parseImpl(self, instring, loc, doActions = True): exc = self.myException exc.loc = loc exc.pstr = instring raise exc class Literal(Token): def __init__(self, matchString): super(Literal, self).__init__() self.match = matchString self.matchLen = len(matchString) try: self.firstMatchChar = matchString[0] except IndexError: warnings.warn('null string passed to Literal; use Empty() instead', SyntaxWarning, stacklevel = 2) self.__class__ = Empty self.name = '"%s"' % _ustr(self.match) self.errmsg = 'Expected ' + self.name self.mayReturnEmpty = False self.mayIndexError = False def parseImpl(self, instring, loc, doActions = True): if instring[loc] == self.firstMatchChar: if self.matchLen == 1 or instring.startswith(self.match, loc): return (loc + self.matchLen, self.match) exc = self.myException exc.loc = loc exc.pstr = instring raise exc return instring[loc] == self.firstMatchChar _L = Literal class Keyword(Token): DEFAULT_KEYWORD_CHARS = alphanums + '_$' def __init__(self, matchString, identChars = DEFAULT_KEYWORD_CHARS, caseless = False): super(Keyword, self).__init__() self.match = matchString self.matchLen = len(matchString) try: self.firstMatchChar = matchString[0] except IndexError: warnings.warn('null string passed to Keyword; use Empty() instead', SyntaxWarning, stacklevel = 2) self.name = '"%s"' % self.match self.errmsg = 'Expected ' + self.name self.mayReturnEmpty = False self.mayIndexError = False self.caseless = caseless if caseless: self.caselessmatch = matchString.upper() identChars = identChars.upper() self.identChars = _str2dict(identChars) def parseImpl(self, instring, loc, doActions = True): if self.caseless: if instring[loc:loc + self.matchLen].upper() == self.caselessmatch: if loc >= len(instring) - self.matchLen or instring[loc + self.matchLen].upper() not in self.identChars: if loc == 0 or instring[loc - 1].upper() not in self.identChars: return (loc + self.matchLen, self.match) elif instring[loc] == self.firstMatchChar: if self.matchLen == 1 or instring.startswith(self.match, loc): if loc >= len(instring) - self.matchLen or instring[loc + self.matchLen] not in self.identChars: if loc == 0 or instring[loc - 1] not in self.identChars: return (loc + self.matchLen, self.match) exc = self.myException exc.loc = loc exc.pstr = instring raise exc return instring[loc + self.matchLen] not in self.identChars def copy(self): c = super(Keyword, self).copy() c.identChars = Keyword.DEFAULT_KEYWORD_CHARS return c def setDefaultKeywordChars(chars): Keyword.DEFAULT_KEYWORD_CHARS = chars setDefaultKeywordChars = staticmethod(setDefaultKeywordChars) class CaselessLiteral(Literal): def __init__(self, matchString): super(CaselessLiteral, self).__init__(matchString.upper()) self.returnString = matchString self.name = "'%s'" % self.returnString self.errmsg = 'Expected ' + self.name def parseImpl(self, instring, loc, doActions = True): if instring[loc:loc + self.matchLen].upper() == self.match: return (loc + self.matchLen, self.returnString) exc = self.myException exc.loc = loc exc.pstr = instring raise exc class CaselessKeyword(Keyword): def __init__(self, matchString, identChars = Keyword.DEFAULT_KEYWORD_CHARS): super(CaselessKeyword, self).__init__(matchString, identChars, caseless = True) def parseImpl(self, instring, loc, doActions = True): if instring[loc:loc + self.matchLen].upper() == self.caselessmatch: if loc >= len(instring) - self.matchLen or instring[loc + self.matchLen].upper() not in self.identChars: return (loc + self.matchLen, self.match) exc = self.myException exc.loc = loc exc.pstr = instring raise exc return instring[loc:loc + self.matchLen].upper() == self.caselessmatch class Word(Token): def __init__(self, initChars, bodyChars = None, min = 1, max = 0, exact = 0, asKeyword = False): super(Word, self).__init__() self.initCharsOrig = initChars self.initChars = _str2dict(initChars) if bodyChars: self.bodyCharsOrig = bodyChars self.bodyChars = _str2dict(bodyChars) else: self.bodyCharsOrig = initChars self.bodyChars = _str2dict(initChars) self.maxSpecified = max > 0 if min < 1: raise ValueError('cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted') min < 1 self.minLen = min if max > 0: self.maxLen = max else: self.maxLen = _MAX_INT if exact > 0: self.maxLen = exact self.minLen = exact self.name = _ustr(self) self.errmsg = 'Expected ' + self.name self.mayIndexError = False self.asKeyword = asKeyword if ' ' not in self.initCharsOrig + self.bodyCharsOrig and min == 1 and max == 0 and exact == 0: if self.bodyCharsOrig == self.initCharsOrig: self.reString = '[%s]+' % _escapeRegexRangeChars(self.initCharsOrig) elif len(self.bodyCharsOrig) == 1: self.reString = '%s[%s]*' % (re.escape(self.initCharsOrig), _escapeRegexRangeChars(self.bodyCharsOrig)) else: self.reString = '[%s][%s]*' % (_escapeRegexRangeChars(self.initCharsOrig), _escapeRegexRangeChars(self.bodyCharsOrig)) if self.asKeyword: self.reString = '\\b' + self.reString + '\\b' try: self.re = re.compile(self.reString) self.re = None def parseImpl(self, instring, loc, doActions = True): if self.re: result = self.re.match(instring, loc) if not result: exc = self.myException exc.loc = loc exc.pstr = instring raise exc result loc = result.end() return (loc, result.group()) if instring[loc] not in self.initChars: exc = self.myException exc.loc = loc exc.pstr = instring raise exc instring[loc] not in self.initChars start = loc loc += 1 instrlen = len(instring) bodychars = self.bodyChars maxloc = start + self.maxLen maxloc = min(maxloc, instrlen) while loc < maxloc and instring[loc] in bodychars: loc += 1 continue self.re throwException = False if loc - start < self.minLen: throwException = True if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: throwException = True if self.asKeyword: if (start > 0 or instring[start - 1] in bodychars or loc < instrlen) and instring[loc] in bodychars: throwException = True if throwException: exc = self.myException exc.loc = loc exc.pstr = instring raise exc throwException return (loc, instring[start:loc]) def __str__(self): try: return super(Word, self).__str__() except: pass if self.strRepr is None: def charsAsStr(s): if len(s) > 4: return s[:4] + '...' return s if self.initCharsOrig != self.bodyCharsOrig: self.strRepr = 'W:(%s,%s)' % (charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig)) else: self.strRepr = 'W:(%s)' % charsAsStr(self.initCharsOrig) return self.strRepr class Regex(Token): def __init__(self, pattern, flags = 0): super(Regex, self).__init__() if len(pattern) == 0: warnings.warn('null string passed to Regex; use Empty() instead', SyntaxWarning, stacklevel = 2) self.pattern = pattern self.flags = flags try: self.re = re.compile(self.pattern, self.flags) self.reString = self.pattern except sre_constants.error: warnings.warn('invalid pattern (%s) passed to Regex' % pattern, SyntaxWarning, stacklevel = 2) raise self.name = _ustr(self) self.errmsg = 'Expected ' + self.name self.mayIndexError = False self.mayReturnEmpty = True def parseImpl(self, instring, loc, doActions = True): result = self.re.match(instring, loc) if not result: exc = self.myException exc.loc = loc exc.pstr = instring raise exc result loc = result.end() d = result.groupdict() ret = ParseResults(result.group()) if d: for k in d: ret[k] = d[k] return (loc, ret) def __str__(self): try: return super(Regex, self).__str__() except: pass if self.strRepr is None: self.strRepr = 'Re:(%s)' % repr(self.pattern) return self.strRepr class QuotedString(Token): def __init__(self, quoteChar, escChar = None, escQuote = None, multiline = False, unquoteResults = True, endQuoteChar = None): super(QuotedString, self).__init__() quoteChar = quoteChar.strip() if len(quoteChar) == 0: warnings.warn('quoteChar cannot be the empty string', SyntaxWarning, stacklevel = 2) raise SyntaxError() len(quoteChar) == 0 if endQuoteChar is None: endQuoteChar = quoteChar else: endQuoteChar = endQuoteChar.strip() if len(endQuoteChar) == 0: warnings.warn('endQuoteChar cannot be the empty string', SyntaxWarning, stacklevel = 2) raise SyntaxError() len(endQuoteChar) == 0 self.quoteChar = quoteChar self.quoteCharLen = len(quoteChar) self.firstQuoteChar = quoteChar[0] self.endQuoteChar = endQuoteChar self.endQuoteCharLen = len(endQuoteChar) self.escChar = escChar self.escQuote = escQuote self.unquoteResults = unquoteResults if multiline: self.flags = re.MULTILINE | re.DOTALL if not escChar is not None or _escapeRegexRangeChars(escChar): pass self.pattern = '%s(?:[^%s%s]' % (re.escape(self.quoteChar), _escapeRegexRangeChars(self.endQuoteChar[0]), '') else: self.flags = 0 if not escChar is not None or _escapeRegexRangeChars(escChar): pass self.pattern = '%s(?:[^%s\\n\\r%s]' % (re.escape(self.quoteChar), _escapeRegexRangeChars(self.endQuoteChar[0]), '') self.pattern += ')*%s' % re.escape(self.endQuoteChar) try: self.re = re.compile(self.pattern, self.flags) self.reString = self.pattern except sre_constants.error: self self None if escChar else None if escQuote else self if len(self.endQuoteChar) > 1 else self warnings.warn('invalid pattern (%s) passed to Regex' % self.pattern, SyntaxWarning, stacklevel = 2) raise except: self self.name = _ustr(self) self.errmsg = 'Expected ' + self.name self.mayIndexError = False self.mayReturnEmpty = True def parseImpl(self, instring, loc, doActions = True): if not instring[loc] == self.firstQuoteChar or self.re.match(instring, loc): pass result = None if not result: exc = self.myException exc.loc = loc exc.pstr = instring raise exc result loc = result.end() ret = result.group() if self.unquoteResults: ret = ret[self.quoteCharLen:-(self.endQuoteCharLen)] if isinstance(ret, basestring): if self.escChar: ret = re.sub(self.escCharReplacePattern, '\\g<1>', ret) if self.escQuote: ret = ret.replace(self.escQuote, self.endQuoteChar) return (loc, ret) def __str__(self): try: return super(QuotedString, self).__str__() except: pass if self.strRepr is None: self.strRepr = 'quoted string, starting with %s ending with %s' % (self.quoteChar, self.endQuoteChar) return self.strRepr class CharsNotIn(Token): def __init__(self, notChars, min = 1, max = 0, exact = 0): super(CharsNotIn, self).__init__() self.skipWhitespace = False self.notChars = notChars if min < 1: raise ValueError('cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted') min < 1 self.minLen = min if max > 0: self.maxLen = max else: self.maxLen = _MAX_INT if exact > 0: self.maxLen = exact self.minLen = exact self.name = _ustr(self) self.errmsg = 'Expected ' + self.name self.mayReturnEmpty = self.minLen == 0 self.mayIndexError = False def parseImpl(self, instring, loc, doActions = True): if instring[loc] in self.notChars: exc = self.myException exc.loc = loc exc.pstr = instring raise exc instring[loc] in self.notChars start = loc loc += 1 notchars = self.notChars maxlen = min(start + self.maxLen, len(instring)) while loc < maxlen and instring[loc] not in notchars: loc += 1 if loc - start < self.minLen: exc = self.myException exc.loc = loc exc.pstr = instring raise exc loc - start < self.minLen return (loc, instring[start:loc]) def __str__(self): try: return super(CharsNotIn, self).__str__() except: pass if self.strRepr is None: if len(self.notChars) > 4: self.strRepr = '!W:(%s...)' % self.notChars[:4] else: self.strRepr = '!W:(%s)' % self.notChars return self.strRepr class White(Token): whiteStrs = { ' ': '<SPC>', '\t': '<TAB>', '\n': '<LF>', '\r': '<CR>', '\x0c': '<FF>' } def __init__(self, ws = ' \t\r\n', min = 1, max = 0, exact = 0): super(White, self).__init__() self.matchWhite = ws []([](_[1])) self.name = []([ White.whiteStrs[c] for c in self.matchWhite ]) self.mayReturnEmpty = True self.errmsg = 'Expected ' + self.name self.minLen = min def parseImpl(self, instring, loc, doActions = True): if instring[loc] not in self.matchWhite: exc = self.myException exc.loc = loc exc.pstr = instring raise exc instring[loc] not in self.matchWhite start = loc loc += 1 maxloc = start + self.maxLen maxloc = min(maxloc, len(instring)) while loc < maxloc and instring[loc] in self.matchWhite: loc += 1 if loc - start < self.minLen: exc = self.myException exc.loc = loc exc.pstr = instring raise exc loc - start < self.minLen return (loc, instring[start:loc]) class _PositionToken(Token): def __init__(self): super(_PositionToken, self).__init__() self.name = self.__class__.__name__ self.mayReturnEmpty = True self.mayIndexError = False class GoToColumn(_PositionToken): def __init__(self, colno): super(GoToColumn, self).__init__() self.col = colno def preParse(self, instring, loc): if col(loc, instring) != self.col: instrlen = len(instring) if self.ignoreExprs: loc = self._skipIgnorables(instring, loc) while loc < instrlen and instring[loc].isspace() and col(loc, instring) != self.col: loc += 1 return loc def parseImpl(self, instring, loc, doActions = True): thiscol = col(loc, instring) if thiscol > self.col: raise ParseException(instring, loc, 'Text not in expected column', self) thiscol > self.col newloc = loc + self.col - thiscol ret = instring[loc:newloc] return (newloc, ret) class LineStart(_PositionToken): def __init__(self): super(LineStart, self).__init__() self.setWhitespaceChars(ParserElement.DEFAULT_WHITE_CHARS.replace('\n', '')) self.errmsg = 'Expected start of line' def preParse(self, instring, loc): preloc = super(LineStart, self).preParse(instring, loc) if instring[preloc] == '\n': loc += 1 return loc def parseImpl(self, instring, loc, doActions = True): if not loc == 0 and loc == self.preParse(instring, 0) or instring[loc - 1] == '\n': exc = self.myException exc.loc = loc exc.pstr = instring raise exc instring[loc - 1] == '\n' return (loc, []) class LineEnd(_PositionToken): def __init__(self): super(LineEnd, self).__init__() self.setWhitespaceChars(ParserElement.DEFAULT_WHITE_CHARS.replace('\n', '')) self.errmsg = 'Expected end of line' def parseImpl(self, instring, loc, doActions = True): if loc < len(instring): if instring[loc] == '\n': return (loc + 1, '\n') exc = self.myException exc.loc = loc exc.pstr = instring raise exc loc < len(instring) if loc == len(instring): return (loc + 1, []) exc = self.myException exc.loc = loc exc.pstr = instring raise exc class StringStart(_PositionToken): def __init__(self): super(StringStart, self).__init__() self.errmsg = 'Expected start of text' def parseImpl(self, instring, loc, doActions = True): if loc != 0: if loc != self.preParse(instring, 0): exc = self.myException exc.loc = loc exc.pstr = instring raise exc loc != self.preParse(instring, 0) return (loc, []) class StringEnd(_PositionToken): def __init__(self): super(StringEnd, self).__init__() self.errmsg = 'Expected end of text' def parseImpl(self, instring, loc, doActions = True): if loc < len(instring): exc = self.myException exc.loc = loc exc.pstr = instring raise exc loc < len(instring) if loc == len(instring): return (loc + 1, []) if loc > len(instring): return (loc, []) exc = self.myException exc.loc = loc exc.pstr = instring raise exc class WordStart(_PositionToken): def __init__(self, wordChars = printables): super(WordStart, self).__init__() self.wordChars = _str2dict(wordChars) self.errmsg = 'Not at the start of a word' def parseImpl(self, instring, loc, doActions = True): if loc != 0: if instring[loc - 1] in self.wordChars or instring[loc] not in self.wordChars: exc = self.myException exc.loc = loc exc.pstr = instring raise exc instring[loc] not in self.wordChars return (loc, []) class WordEnd(_PositionToken): def __init__(self, wordChars = printables): super(WordEnd, self).__init__() self.wordChars = _str2dict(wordChars) self.skipWhitespace = False self.errmsg = 'Not at the end of a word' def parseImpl(self, instring, loc, doActions = True): instrlen = len(instring) if instrlen > 0 and loc < instrlen: if instring[loc] in self.wordChars or instring[loc - 1] not in self.wordChars: exc = self.myException exc.loc = loc exc.pstr = instring raise exc instring[loc - 1] not in self.wordChars return (loc, []) class ParseExpression(ParserElement): def __init__(self, exprs, savelist = False): super(ParseExpression, self).__init__(savelist) if isinstance(exprs, list): self.exprs = exprs elif isinstance(exprs, basestring): self.exprs = [ Literal(exprs)] else: self.exprs = [ exprs] self.callPreparse = False def __getitem__(self, i): return self.exprs[i] def append(self, other): self.exprs.append(other) self.strRepr = None return self def leaveWhitespace(self): self.skipWhitespace = False self.exprs = [ e.copy() for e in self.exprs ] for e in self.exprs: e.leaveWhitespace() return self def ignore(self, other): if isinstance(other, Suppress): if other not in self.ignoreExprs: super(ParseExpression, self).ignore(other) for e in self.exprs: e.ignore(self.ignoreExprs[-1]) else: super(ParseExpression, self).ignore(other) for e in self.exprs: e.ignore(self.ignoreExprs[-1]) return self def __str__(self): try: return super(ParseExpression, self).__str__() except: pass if self.strRepr is None: self.strRepr = '%s:(%s)' % (self.__class__.__name__, _ustr(self.exprs)) return self.strRepr def streamline(self): super(ParseExpression, self).streamline() for e in self.exprs: e.streamline() if len(self.exprs) == 2: other = self.exprs[0] other = self.exprs[-1] if isinstance(other, self.__class__) and not (other.parseAction) and other.resultsName is None and not (other.debug): self.exprs = self.exprs[:-1] + other.exprs[:] self.strRepr = None self.mayReturnEmpty |= other.mayReturnEmpty self.mayIndexError |= other.mayIndexError return self def setResultsName(self, name, listAllMatches = False): ret = super(ParseExpression, self).setResultsName(name, listAllMatches) return ret def validate(self, validateTrace = []): tmp = validateTrace[:] + [ self] for e in self.exprs: e.validate(tmp) self.checkRecursion([]) class And(ParseExpression): class _ErrorStop(Empty): def __init__(self, *args, **kwargs): super(Empty, self).__init__(*args, **kwargs) self.leaveWhitespace() def __init__(self, exprs, savelist = True): super(And, self).__init__(exprs, savelist) self.mayReturnEmpty = True for e in self.exprs: if not e.mayReturnEmpty: self.mayReturnEmpty = False break continue self.setWhitespaceChars(exprs[0].whiteChars) self.skipWhitespace = exprs[0].skipWhitespace self.callPreparse = True def parseImpl(self, instring, loc, doActions = True): (loc, resultlist) = self.exprs[0]._parse(instring, loc, doActions, callPreParse = False) errorStop = False for e in self.exprs[1:]: if isinstance(e, And._ErrorStop): errorStop = True continue if errorStop: try: (loc, exprtokens) = e._parse(instring, loc, doActions) except ParseSyntaxException: raise except ParseBaseException: pe = None raise ParseSyntaxException(pe) except IndexError: ie = None raise ParseSyntaxException(ParseException(instring, len(instring), self.errmsg, self)) except: None<EXCEPTION MATCH>ParseSyntaxException None<EXCEPTION MATCH>ParseSyntaxException (loc, exprtokens) = e._parse(instring, loc, doActions) if exprtokens or exprtokens.keys(): resultlist += exprtokens continue return (loc, resultlist) def __iadd__(self, other): if isinstance(other, basestring): other = Literal(other) return self.append(other) def checkRecursion(self, parseElementList): subRecCheckList = parseElementList[:] + [ self] for e in self.exprs: e.checkRecursion(subRecCheckList) if not e.mayReturnEmpty: break continue def __str__(self): if hasattr(self, 'name'): return self.name return self.strRepr class Or(ParseExpression): def __init__(self, exprs, savelist = False): super(Or, self).__init__(exprs, savelist) self.mayReturnEmpty = False for e in self.exprs: if e.mayReturnEmpty: self.mayReturnEmpty = True break continue def parseImpl(self, instring, loc, doActions = True): maxExcLoc = -1 maxMatchLoc = -1 maxException = None for e in self.exprs: try: loc2 = e.tryParse(instring, loc) except ParseException: err = None if err.loc > maxExcLoc: maxException = err maxExcLoc = err.loc err.loc > maxExcLoc except IndexError: if len(instring) > maxExcLoc: maxException = ParseException(instring, len(instring), e.errmsg, self) maxExcLoc = len(instring) len(instring) > maxExcLoc elif loc2 > maxMatchLoc: maxMatchLoc = loc2 maxMatchExp = e continue if maxMatchLoc < 0: if maxException is not None: raise maxException maxException is not None raise ParseException(instring, loc, 'no defined alternatives to match', self) maxMatchLoc < 0 return maxMatchExp._parse(instring, loc, doActions) def __ixor__(self, other): if isinstance(other, basestring): other = Literal(other) return self.append(other) def __str__(self): if hasattr(self, 'name'): return self.name return self.strRepr def checkRecursion(self, parseElementList): subRecCheckList = parseElementList[:] + [ self] for e in self.exprs: e.checkRecursion(subRecCheckList) class MatchFirst(ParseExpression): def __init__(self, exprs, savelist = False): super(MatchFirst, self).__init__(exprs, savelist) if exprs: self.mayReturnEmpty = False for e in self.exprs: if e.mayReturnEmpty: self.mayReturnEmpty = True break continue else: self.mayReturnEmpty = True def parseImpl(self, instring, loc, doActions = True): maxExcLoc = -1 maxException = None for e in self.exprs: try: ret = e._parse(instring, loc, doActions) return ret continue except ParseException: err = None if err.loc > maxExcLoc: maxException = err maxExcLoc = err.loc err.loc > maxExcLoc except IndexError: if len(instring) > maxExcLoc: maxException = ParseException(instring, len(instring), e.errmsg, self) maxExcLoc = len(instring) len(instring) > maxExcLoc if maxException is not None: raise maxException raise ParseException(instring, loc, 'no defined alternatives to match', self) return None def __ior__(self, other): if isinstance(other, basestring): other = Literal(other) return self.append(other) def __str__(self): if hasattr(self, 'name'): return self.name return self.strRepr def checkRecursion(self, parseElementList): subRecCheckList = parseElementList[:] + [ self] for e in self.exprs: e.checkRecursion(subRecCheckList) class Each(ParseExpression): def __init__(self, exprs, savelist = True): super(Each, self).__init__(exprs, savelist) self.mayReturnEmpty = True for e in self.exprs: if not e.mayReturnEmpty: self.mayReturnEmpty = False break continue self.skipWhitespace = True self.initExprGroups = True def parseImpl(self, instring, loc, doActions = True): tmpLoc = loc tmpReqd = self.required[:] tmpOpt = self.optionals[:] matchOrder = [] keepMatching = True while keepMatching: tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired failed = [] for e in tmpExprs: try: tmpLoc = e.tryParse(instring, tmpLoc) except ParseException: [] if self.initExprGroups else [] [] if self.initExprGroups else [] [] failed.append(e) continue [] matchOrder.append(e) if e in tmpReqd: tmpReqd.remove(e) continue [] if self.initExprGroups else [] if e in tmpOpt: tmpOpt.remove(e) continue [] if len(failed) == len(tmpExprs): keepMatching = False continue [] continue [] if tmpReqd: missing = []([ _ustr(e) for e in tmpReqd ]) raise ParseException(instring, loc, 'Missing one or more required elements (%s)' % missing) tmpReqd [] += _[6] resultlist = [] for e in matchOrder: (loc, results) = e._parse(instring, loc, doActions) resultlist.append(results) finalResults = ParseResults([]) for r in resultlist: dups = { } for k in r.keys(): if k in finalResults.keys(): tmp = ParseResults(finalResults[k]) tmp += ParseResults(r[k]) dups[k] = tmp continue [] finalResults += ParseResults(r) for k, v in dups.items(): finalResults[k] = v return (loc, finalResults) def __str__(self): if hasattr(self, 'name'): return self.name return self.strRepr def checkRecursion(self, parseElementList): subRecCheckList = parseElementList[:] + [ self] for e in self.exprs: e.checkRecursion(subRecCheckList) class ParseElementEnhance(ParserElement): def __init__(self, expr, savelist = False): super(ParseElementEnhance, self).__init__(savelist) if isinstance(expr, basestring): expr = Literal(expr) self.expr = expr self.strRepr = None if expr is not None: self.mayIndexError = expr.mayIndexError self.mayReturnEmpty = expr.mayReturnEmpty self.setWhitespaceChars(expr.whiteChars) self.skipWhitespace = expr.skipWhitespace self.saveAsList = expr.saveAsList self.callPreparse = expr.callPreparse self.ignoreExprs.extend(expr.ignoreExprs) def parseImpl(self, instring, loc, doActions = True): if self.expr is not None: return self.expr._parse(instring, loc, doActions, callPreParse = False) raise ParseException('', loc, self.errmsg, self) def leaveWhitespace(self): self.skipWhitespace = False self.expr = self.expr.copy() if self.expr is not None: self.expr.leaveWhitespace() return self def ignore(self, other): if isinstance(other, Suppress): if other not in self.ignoreExprs: super(ParseElementEnhance, self).ignore(other) if self.expr is not None: self.expr.ignore(self.ignoreExprs[-1]) else: super(ParseElementEnhance, self).ignore(other) if self.expr is not None: self.expr.ignore(self.ignoreExprs[-1]) return self def streamline(self): super(ParseElementEnhance, self).streamline() if self.expr is not None: self.expr.streamline() return self def checkRecursion(self, parseElementList): if self in parseElementList: raise RecursiveGrammarException(parseElementList + [ self]) self in parseElementList subRecCheckList = parseElementList[:] + [ self] if self.expr is not None: self.expr.checkRecursion(subRecCheckList) def validate(self, validateTrace = []): tmp = validateTrace[:] + [ self] if self.expr is not None: self.expr.validate(tmp) self.checkRecursion([]) def __str__(self): try: return super(ParseElementEnhance, self).__str__() except: pass if self.strRepr is None and self.expr is not None: self.strRepr = '%s:(%s)' % (self.__class__.__name__, _ustr(self.expr)) return self.strRepr class FollowedBy(ParseElementEnhance): def __init__(self, expr): super(FollowedBy, self).__init__(expr) self.mayReturnEmpty = True def parseImpl(self, instring, loc, doActions = True): self.expr.tryParse(instring, loc) return (loc, []) class NotAny(ParseElementEnhance): def __init__(self, expr): super(NotAny, self).__init__(expr) self.skipWhitespace = False self.mayReturnEmpty = True self.errmsg = 'Found unwanted token, ' + _ustr(self.expr) def parseImpl(self, instring, loc, doActions = True): try: self.expr.tryParse(instring, loc) except (ParseException, IndexError): pass exc = self.myException exc.loc = loc exc.pstr = instring raise exc return (loc, []) def __str__(self): if hasattr(self, 'name'): return self.name if self.strRepr is None: self.strRepr = '~{' + _ustr(self.expr) + '}' return self.strRepr class ZeroOrMore(ParseElementEnhance): def __init__(self, expr): super(ZeroOrMore, self).__init__(expr) self.mayReturnEmpty = True def parseImpl(self, instring, loc, doActions = True): tokens = [] try: (loc, tokens) = self.expr._parse(instring, loc, doActions, callPreParse = False) hasIgnoreExprs = len(self.ignoreExprs) > 0 while hasIgnoreExprs: preloc = self._skipIgnorables(instring, loc) preloc = loc (loc, tmptokens) = self.expr._parse(instring, preloc, doActions) if tmptokens or tmptokens.keys(): tokens += tmptokens continue except (ParseException, IndexError): pass return (loc, tokens) def __str__(self): if hasattr(self, 'name'): return self.name if self.strRepr is None: self.strRepr = '[' + _ustr(self.expr) + ']...' return self.strRepr def setResultsName(self, name, listAllMatches = False): ret = super(ZeroOrMore, self).setResultsName(name, listAllMatches) ret.saveAsList = True return ret class OneOrMore(ParseElementEnhance): def parseImpl(self, instring, loc, doActions = True): (loc, tokens) = self.expr._parse(instring, loc, doActions, callPreParse = False) try: hasIgnoreExprs = len(self.ignoreExprs) > 0 while hasIgnoreExprs: preloc = self._skipIgnorables(instring, loc) preloc = loc (loc, tmptokens) = self.expr._parse(instring, preloc, doActions) if tmptokens or tmptokens.keys(): tokens += tmptokens continue except (ParseException, IndexError): pass return (loc, tokens) def __str__(self): if hasattr(self, 'name'): return self.name if self.strRepr is None: self.strRepr = '{' + _ustr(self.expr) + '}...' return self.strRepr def setResultsName(self, name, listAllMatches = False): ret = super(OneOrMore, self).setResultsName(name, listAllMatches) ret.saveAsList = True return ret class _NullToken(object): def __bool__(self): return False __nonzero__ = __bool__ def __str__(self): return '' _optionalNotMatched = _NullToken() class Optional(ParseElementEnhance): def __init__(self, exprs, default = _optionalNotMatched): super(Optional, self).__init__(exprs, savelist = False) self.defaultValue = default self.mayReturnEmpty = True def parseImpl(self, instring, loc, doActions = True): try: (loc, tokens) = self.expr._parse(instring, loc, doActions, callPreParse = False) except (ParseException, IndexError): if self.defaultValue is not _optionalNotMatched: if self.expr.resultsName: tokens = ParseResults([ self.defaultValue]) tokens[self.expr.resultsName] = self.defaultValue else: tokens = [ self.defaultValue] else: tokens = [] except: self.defaultValue is not _optionalNotMatched return (loc, tokens) def __str__(self): if hasattr(self, 'name'): return self.name if self.strRepr is None: self.strRepr = '[' + _ustr(self.expr) + ']' return self.strRepr class SkipTo(ParseElementEnhance): def __init__(self, other, include = False, ignore = None, failOn = None): super(SkipTo, self).__init__(other) if ignore is not None: self.expr = self.expr.copy() self.expr.ignore(ignore) self.mayReturnEmpty = True self.mayIndexError = False self.includeMatch = include self.asList = False if failOn is not None and isinstance(failOn, basestring): self.failOn = Literal(failOn) else: self.failOn = failOn self.errmsg = 'No match found for ' + _ustr(self.expr) def parseImpl(self, instring, loc, doActions = True): startLoc = loc instrlen = len(instring) expr = self.expr failParse = False while loc <= instrlen: try: if self.failOn: failParse = True self.failOn.tryParse(instring, loc) failParse = False loc = expr._skipIgnorables(instring, loc) expr._parse(instring, loc, doActions = False, callPreParse = False) skipText = instring[startLoc:loc] if self.includeMatch: (loc, mat) = expr._parse(instring, loc, doActions, callPreParse = False) if mat: skipRes = ParseResults(skipText) skipRes += mat return (loc, [ skipRes]) return (loc, [ skipText]) self.includeMatch return (loc, [ skipText]) continue except (ParseException, IndexError): if failParse: raise failParse loc += 1 continue None<EXCEPTION MATCH>(ParseException, IndexError) exc = self.myException exc.loc = loc exc.pstr = instring raise exc class Forward(ParseElementEnhance): def __init__(self, other = None): super(Forward, self).__init__(other, savelist = False) def __lshift__(self, other): if isinstance(other, basestring): other = Literal(other) self.expr = other self.mayReturnEmpty = other.mayReturnEmpty self.strRepr = None self.mayIndexError = self.expr.mayIndexError self.mayReturnEmpty = self.expr.mayReturnEmpty self.setWhitespaceChars(self.expr.whiteChars) self.skipWhitespace = self.expr.skipWhitespace self.saveAsList = self.expr.saveAsList self.ignoreExprs.extend(self.expr.ignoreExprs) def leaveWhitespace(self): self.skipWhitespace = False return self def streamline(self): if not self.streamlined: self.streamlined = True if self.expr is not None: self.expr.streamline() return self def validate(self, validateTrace = []): if self not in validateTrace: tmp = validateTrace[:] + [ self] if self.expr is not None: self.expr.validate(tmp) self.checkRecursion([]) def __str__(self): if hasattr(self, 'name'): return self.name self._revertClass = self.__class__ self.__class__ = _ForwardNoRecurse try: if self.expr is not None: retString = _ustr(self.expr) else: retString = 'None' finally: self.__class__ = self._revertClass return self.__class__.__name__ + ': ' + retString def copy(self): if self.expr is not None: return super(Forward, self).copy() ret = Forward() ret << self return ret class _ForwardNoRecurse(Forward): def __str__(self): return '...' class TokenConverter(ParseElementEnhance): def __init__(self, expr, savelist = False): super(TokenConverter, self).__init__(expr) self.saveAsList = False class Upcase(TokenConverter): def __init__(self, *args): super(Upcase, self).__init__(*args) warnings.warn('Upcase class is deprecated, use upcaseTokens parse action instead', DeprecationWarning, stacklevel = 2) def postParse(self, instring, loc, tokenlist): return list(map(string.upper, tokenlist)) class Combine(TokenConverter): def __init__(self, expr, joinString = '', adjacent = True): super(Combine, self).__init__(expr) if adjacent: self.leaveWhitespace() self.adjacent = adjacent self.skipWhitespace = True self.joinString = joinString def ignore(self, other): if self.adjacent: ParserElement.ignore(self, other) else: super(Combine, self).ignore(other) return self def postParse(self, instring, loc, tokenlist): retToks = tokenlist.copy() del retToks[:] retToks += ParseResults([ ''.join(tokenlist._asStringList(self.joinString))], modal = self.modalResults) if self.resultsName and len(retToks.keys()) > 0: return [ retToks] return retToks class Group(TokenConverter): def __init__(self, expr): super(Group, self).__init__(expr) self.saveAsList = True def postParse(self, instring, loc, tokenlist): return [ tokenlist] class Dict(TokenConverter): def __init__(self, exprs): super(Dict, self).__init__(exprs) self.saveAsList = True def postParse(self, instring, loc, tokenlist): for i, tok in enumerate(tokenlist): if len(tok) == 0: continue ikey = tok[0] if isinstance(ikey, int): ikey = _ustr(tok[0]).strip() if len(tok) == 1: tokenlist[ikey] = _ParseResultsWithOffset('', i) continue if len(tok) == 2 and not isinstance(tok[1], ParseResults): tokenlist[ikey] = _ParseResultsWithOffset(tok[1], i) continue dictvalue = tok.copy() del dictvalue[0] if (len(dictvalue) != 1 or isinstance(dictvalue, ParseResults)) and dictvalue.keys(): tokenlist[ikey] = _ParseResultsWithOffset(dictvalue, i) continue tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0], i) if self.resultsName: return [ tokenlist] return tokenlist class Suppress(TokenConverter): def postParse(self, instring, loc, tokenlist): return [] def suppress(self): return self class OnlyOnce(object): def __init__(self, methodCall): self.callable = ParserElement._normalizeParseActionArgs(methodCall) self.called = False def __call__(self, s, l, t): if not self.called: results = self.callable(s, l, t) self.called = True return results raise ParseException(s, l, '') def reset(self): self.called = False def traceParseAction(f): f = ParserElement._normalizeParseActionArgs(f) def z(*paArgs): thisFunc = f.func_name (s, l, t) = paArgs[-3:] if len(paArgs) > 3: thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc sys.stderr.write(">>entering %s(line: '%s', %d, %s)\n" % (thisFunc, line(l, s), l, t)) try: ret = f(*paArgs) except Exception: exc = None sys.stderr.write('<<leaving %s (exception: %s)\n' % (thisFunc, exc)) raise sys.stderr.write('<<leaving %s (ret: %s)\n' % (thisFunc, ret)) return ret try: z.__name__ = f.__name__ except AttributeError: (None,) (None,) except: (None,) return z def delimitedList(expr, delim = ',', combine = False): dlName = _ustr(expr) + ' [' + _ustr(delim) + ' ' + _ustr(expr) + ']...' if combine: return Combine(expr + ZeroOrMore(delim + expr)).setName(dlName) return (expr + ZeroOrMore(Suppress(delim) + expr)).setName(dlName) def countedArray(expr): arrayExpr = Forward() def countFieldParseAction(s, l, t): n = int(t[0]) if not n or Group(And([ expr] * n)): pass arrayExpr << Group(empty) return [] return Word(nums).setName('arrayLen').setParseAction(countFieldParseAction, callDuringTry = True) + arrayExpr def _flatten(L): if type(L) is not list: return [ L] if L == []: return L return _flatten(L[0]) + _flatten(L[1:]) def matchPreviousLiteral(expr): rep = Forward() def copyTokenToRepeater(s, l, t): pass expr.addParseAction(copyTokenToRepeater, callDuringTry = True) return rep def matchPreviousExpr(expr): rep = Forward() e2 = expr.copy() rep << e2 def copyTokenToRepeater(s, l, t): matchTokens = _flatten(t.asList()) def mustMatchTheseTokens(s, l, t): theseTokens = _flatten(t.asList()) if theseTokens != matchTokens: raise ParseException('', 0, '') theseTokens != matchTokens rep.setParseAction(mustMatchTheseTokens, callDuringTry = True) expr.addParseAction(copyTokenToRepeater, callDuringTry = True) return rep def _escapeRegexRangeChars(s): for c in '\\^-]': s = s.replace(c, _bslash + c) s = s.replace('\n', '\\n') s = s.replace('\t', '\\t') return _ustr(s) def oneOf(strs, caseless = False, useRegex = True): if caseless: isequal = lambda a, b: a.upper() == b.upper() masks = lambda a, b: b.upper().startswith(a.upper()) parseElementClass = CaselessLiteral else: isequal = lambda a, b: a == b masks = lambda a, b: b.startswith(a) parseElementClass = Literal if isinstance(strs, (list, tuple)): symbols = strs[:] elif isinstance(strs, basestring): symbols = strs.split() else: warnings.warn('Invalid argument to oneOf, expected string or list', SyntaxWarning, stacklevel = 2) i = 0 while i < len(symbols) - 1: cur = symbols[i] for j, other in enumerate(symbols[i + 1:]): if isequal(other, cur): del symbols[i + j + 1] break continue if masks(cur, other): del symbols[i + j + 1] symbols.insert(i, other) cur = other break continue else: i += 1 if not caseless and useRegex: try: if len(symbols) == len(''.join(symbols)): return ''.join([] % []([ _escapeRegexRangeChars(sym) for sym in symbols ])) return []([]([ re.escape(sym) for sym in symbols ])) warnings.warn('Exception creating Regex for oneOf, building MatchFirst', SyntaxWarning, stacklevel = 2) return []([ parseElementClass(sym) for sym in symbols ]) def dictOf(key, value): return Dict(ZeroOrMore(Group(key + value))) def originalTextFor(expr, asString = True): locMarker = Empty().setParseAction((lambda s, loc, t: loc)) matchExpr = locMarker('_original_start') + expr + locMarker('_original_end') if asString: extractText = lambda s, l, t: s[t._original_start:t._original_end] else: def extractText(s, l, t): del t[:] t.insert(0, s[t._original_start:t._original_end]) del t['_original_start'] del t['_original_end'] matchExpr.setParseAction(extractText) return matchExpr empty = Empty().setName('empty') lineStart = LineStart().setName('lineStart') lineEnd = LineEnd().setName('lineEnd') stringStart = StringStart().setName('stringStart') stringEnd = StringEnd().setName('stringEnd') _escapedPunc = Word(_bslash, '\\[]-*.$+^?()~ ', exact = 2).setParseAction((lambda s, l, t: t[0][1])) _printables_less_backslash = []([] if c not in '\\]' else _[2]) _escapedHexChar = Combine(Suppress(_bslash + '0x') + Word(hexnums)).setParseAction((lambda s, l, t: unichr(int(t[0], 16)))) _escapedOctChar = Combine(Suppress(_bslash) + Word('0', '01234567')).setParseAction((lambda s, l, t: unichr(int(t[0], 8)))) _singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | Word(_printables_less_backslash, exact = 1) _charRange = Group(_singleChar + Suppress('-') + _singleChar) _reBracketExpr = Literal('[') + Optional('^').setResultsName('negate') + Group(OneOrMore(_charRange | _singleChar)).setResultsName('body') + ']' _expanded = lambda p: if not isinstance(p, ParseResults) or []([ unichr(c) for c in range(ord(p[0]), ord(p[1]) + 1) ]): passp def srange(s): try: return []([ _expanded(part) for part in _reBracketExpr.parseString(s).body ]) except: return '' def matchOnlyAtCol(n): def verifyCol(strg, locn, toks): if col(locn, strg) != n: raise ParseException(strg, locn, 'matched token not at column %d' % n) col(locn, strg) != n return verifyCol def replaceWith(replStr): def _replFunc(*args): return [ replStr] return _replFunc def removeQuotes(s, l, t): return t[0][1:-1] def upcaseTokens(s, l, t): return [ tt.upper() for tt in map(_ustr, t) ] def downcaseTokens(s, l, t): return [ tt.lower() for tt in map(_ustr, t) ] def keepOriginalText(s, startLoc, t): try: endloc = getTokensEndLoc() except ParseException: raise ParseFatalException('incorrect usage of keepOriginalText - may only be called as a parse action') del t[:] t += ParseResults(s[startLoc:endloc]) return t def getTokensEndLoc(): import inspect fstack = inspect.stack() try: for f in fstack[2:]: if f[3] == '_parseNoCache': endloc = f[0].f_locals['loc'] return endloc else: raise ParseFatalException('incorrect usage of getTokensEndLoc - may only be called from within a parse action') del fstack return None def _makeTags(tagStr, xml): if isinstance(tagStr, basestring): resname = tagStr tagStr = Keyword(tagStr, caseless = not xml) else: resname = tagStr.name tagAttrName = Word(alphas, alphanums + '_-:') closeTag = Combine(_L('</') + tagStr + '>') openTag = openTag.setResultsName('start' + ''.join(resname.replace(':', ' ').title().split())).setName('<%s>' % tagStr) closeTag = closeTag.setResultsName('end' + ''.join(resname.replace(':', ' ').title().split())).setName('</%s>' % tagStr) return (openTag, closeTag) def makeHTMLTags(tagStr): return _makeTags(tagStr, False) def makeXMLTags(tagStr): return _makeTags(tagStr, True) def withAttribute(*args, **attrDict): if args: attrs = args[:] else: attrs = attrDict.items() attrs = [ (k, v) for k, v in attrs ] def pa(s, l, tokens): for attrName, attrValue in attrs: if attrName not in tokens: raise ParseException(s, l, 'no matching attribute ' + attrName) attrName not in tokens if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: raise ParseException(s, l, "attribute '%s' has value '%s', must be '%s'" % (attrName, tokens[attrName], attrValue)) tokens[attrName] != attrValue return pa withAttribute.ANY_VALUE = object() opAssoc = _Constants() opAssoc.LEFT = object() opAssoc.RIGHT = object() def operatorPrecedence(baseExpr, opList): ret = Forward() lastExpr = baseExpr | Suppress('(') + ret + Suppress(')') for i, operDef in enumerate(opList): (opExpr, arity, rightLeftAssoc, pa) = operDef + (None,)[:4] if arity == 3: if opExpr is None or len(opExpr) != 2: raise ValueError('if numterms=3, opExpr must be a tuple or list of two expressions') len(opExpr) != 2 (opExpr1, opExpr2) = opExpr thisExpr = Forward() if rightLeftAssoc == opAssoc.LEFT: if arity == 1: matchExpr = FollowedBy(lastExpr + opExpr) + Group(lastExpr + OneOrMore(opExpr)) elif arity == 2: if opExpr is not None: matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group(lastExpr + OneOrMore(opExpr + lastExpr)) else: matchExpr = FollowedBy(lastExpr + lastExpr) + Group(lastExpr + OneOrMore(lastExpr)) elif arity == 3: matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + Group(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) else: raise ValueError('operator must be unary (1), binary (2), or ternary (3)') arity == 1 if rightLeftAssoc == opAssoc.RIGHT: if arity == 1: if not isinstance(opExpr, Optional): opExpr = Optional(opExpr) matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group(opExpr + thisExpr) elif arity == 2: if opExpr is not None: matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group(lastExpr + OneOrMore(opExpr + thisExpr)) else: matchExpr = FollowedBy(lastExpr + thisExpr) + Group(lastExpr + OneOrMore(thisExpr)) elif arity == 3: matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + Group(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) else: raise ValueError('operator must be unary (1), binary (2), or ternary (3)') arity == 1 raise ValueError('operator must indicate right or left associativity') if pa: matchExpr.setParseAction(pa) thisExpr << (matchExpr | lastExpr) lastExpr = thisExpr ret << lastExpr return ret dblQuotedString = Regex('"(?:[^"\\n\\r\\\\]|(?:"")|(?:\\\\x[0-9a-fA-F]+)|(?:\\\\.))*"').setName('string enclosed in double quotes') sglQuotedString = Regex("'(?:[^'\\n\\r\\\\]|(?:'')|(?:\\\\x[0-9a-fA-F]+)|(?:\\\\.))*'").setName('string enclosed in single quotes') quotedString = Regex('(?:"(?:[^"\\n\\r\\\\]|(?:"")|(?:\\\\x[0-9a-fA-F]+)|(?:\\\\.))*")|(?:\'(?:[^\'\\n\\r\\\\]|(?:\'\')|(?:\\\\x[0-9a-fA-F]+)|(?:\\\\.))*\')').setName('quotedString using single or double quotes') unicodeString = Combine(_L('u') + quotedString.copy()) def nestedExpr(opener = '(', closer = ')', content = None, ignoreExpr = quotedString): if opener == closer: raise ValueError('opening and closing strings cannot be the same') opener == closer if content is None: if isinstance(opener, basestring) and isinstance(closer, basestring): if len(opener) == 1 and len(closer) == 1: if ignoreExpr is not None: content = Combine(OneOrMore(~ignoreExpr + CharsNotIn(opener + closer + ParserElement.DEFAULT_WHITE_CHARS, exact = 1))).setParseAction((lambda t: t[0].strip())) else: content = empty + CharsNotIn(opener + closer + ParserElement.DEFAULT_WHITE_CHARS).setParseAction((lambda t: t[0].strip())) elif ignoreExpr is not None: content = Combine(OneOrMore(~ignoreExpr + ~Literal(opener) + ~Literal(closer) + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS, exact = 1))).setParseAction((lambda t: t[0].strip())) else: content = Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS, exact = 1))).setParseAction((lambda t: t[0].strip())) else: raise ValueError('opening and closing arguments must be strings if no content expression is given') isinstance(closer, basestring) ret = Forward() if ignoreExpr is not None: ret << Group(Suppress(opener) + ZeroOrMore(ignoreExpr | ret | content) + Suppress(closer)) else: ret << Group(Suppress(opener) + ZeroOrMore(ret | content) + Suppress(closer)) return ret def indentedBlock(blockStatementExpr, indentStack, indent = True): def checkPeerIndent(s, l, t): if l >= len(s): return None curCol = col(l, s) if curCol != indentStack[-1]: if curCol > indentStack[-1]: raise ParseFatalException(s, l, 'illegal nesting') curCol > indentStack[-1] raise ParseException(s, l, 'not a peer entry') curCol != indentStack[-1] def checkSubIndent(s, l, t): curCol = col(l, s) if curCol > indentStack[-1]: indentStack.append(curCol) else: raise ParseException(s, l, 'not a subentry') return curCol > indentStack[-1] def checkUnindent(s, l, t): if l >= len(s): return None curCol = col(l, s) if not indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]: raise ParseException(s, l, 'not an unindent') curCol <= indentStack[-2] indentStack.pop() NL = OneOrMore(LineEnd().setWhitespaceChars('\t ').suppress()) INDENT = Empty() + Empty().setParseAction(checkSubIndent) PEER = Empty().setParseAction(checkPeerIndent) UNDENT = Empty().setParseAction(checkUnindent) if indent: smExpr = Group(Optional(NL) + FollowedBy(blockStatementExpr) + INDENT + OneOrMore(PEER + Group(blockStatementExpr) + Optional(NL)) + UNDENT) else: smExpr = Group(Optional(NL) + OneOrMore(PEER + Group(blockStatementExpr) + Optional(NL))) blockStatementExpr.ignore(_bslash + LineEnd()) return smExpr alphas8bit = srange('[\\0xc0-\\0xd6\\0xd8-\\0xf6\\0xf8-\\0xff]') punc8bit = srange('[\\0xa1-\\0xbf\\0xd7\\0xf7]') (anyOpenTag, anyCloseTag) = makeHTMLTags(Word(alphas, alphanums + '_:')) commonHTMLEntity = Combine(_L('&') + oneOf('gt lt amp nbsp quot').setResultsName('entity') + ';') _htmlEntityMap = dict(zip('gt lt amp nbsp quot'.split(), '><& "')) replaceHTMLEntity = lambda t: if not t.entity in _htmlEntityMap or _htmlEntityMap[t.entity]: pass cStyleComment = Regex('/\\*(?:[^*]*\\*+)+?/').setName('C style comment') htmlComment = Regex('<!--[\\s\\S]*?-->') restOfLine = Regex('.*').leaveWhitespace() dblSlashComment = Regex('\\/\\/(\\\\\\n|.)*').setName('// comment') cppStyleComment = Regex('/(?:\\*(?:[^*]*\\*+)+?/|/[^\\n]*(?:\\n[^\\n]*)*?(?:(?<!\\\\)|\\Z))').setName('C++ style comment') javaStyleComment = cppStyleComment pythonStyleComment = Regex('#.*').setName('Python style comment') _noncomma = []([] if c != ',' else _[3]) _commasepitem = Combine(OneOrMore(Word(_noncomma) + Optional(Word(' \t') + ~Literal(',') + ~LineEnd()))).streamline().setName('commaItem') commaSeparatedList = delimitedList(Optional(quotedString | _commasepitem, default = '')).setName('commaSeparatedList')