|
Server : Apache/2.2.2 (Fedora) System : Linux App1.pathumtani.go.th 2.6.20-1.2320.fc5smp #1 SMP Tue Jun 12 19:40:16 EDT 2007 i686 User : apache ( 48) PHP Version : 5.2.9 Disable Function : NONE Directory : /proc/self/root/usr/lib/python2.4/site-packages/_xmlplus/xpath/ |
Upload File : |
# -*- coding: utf-8 -*-
# Parser for XPath in -*- python -*-, as defined in REC-xpath-19991116
# Copyright 2000, Martin v. Löwis
# This parser is generated by Amit J Patel's YAPPS
# http://theory.stanford.edu/~amitp/Yapps/ for documentation and updates
# The generated Scanner class is not used, and redefined at the end.
# Therefore, the token definitions are for illustration only, and to
# let YAPPS know what the tokens are.
# The grammar rules attempt to follow the XPath recommendation closely,
# both in textual order and presentation. The following changes have been
# made:
# - left-recursion was replaced with right-recursion
# - left-factorization was applied where necessary
# - semantic values were attached to non-terminals
from string import *
import re
from yappsrt import *
class XPathScanner(Scanner):
patterns = [
("'mod'", re.compile('mod')),
("'div'", re.compile('div')),
("'-'", re.compile('-')),
("'>='", re.compile('>=')),
("'>'", re.compile('>')),
("'<='", re.compile('<=')),
("'<'", re.compile('<')),
("'!='", re.compile('!=')),
("'='", re.compile('=')),
("'and'", re.compile('and')),
("'or'", re.compile('or')),
("','", re.compile(',')),
("'@'", re.compile('@')),
("'::'", re.compile('::')),
("'//'", re.compile('//')),
("'/'", re.compile('/')),
('Literal', re.compile('"[^"]*"|\'[^\']*')),
('Number', re.compile('\\d+(.\\d*)?|.\\d+')),
('VariableReference', re.compile('\\$[a-zA-Z_][:a-zA-Z0-9_.-]*')),
('NodeType', re.compile('comment|text|processing-instruction|node')),
('AxisName', re.compile('ancestor|ancestor-or-self|attribute|child|descendant|descendant-or-self|following|following-sibling|namespace|parent|preceding|preceding-sibling|self')),
('NCName', re.compile('[a-zA-Z_][a-zA-Z0-9_.-]*')),
('NCNameStar', re.compile('[a-zA-Z_][a-zA-Z0-9_.-]*:\\*')),
('QName', re.compile('[a-zA-Z_][a-zA-Z0-9_.-]*(:[a-zA-Z_][a-zA-Z0-9_.-])?')),
('MultiplyOperator', re.compile('\\*')),
('LPAREN', re.compile('\\(')),
('RPAREN', re.compile('\\)')),
('STAR', re.compile('\\*')),
('PLUS', re.compile('\\+')),
('LBRACKET', re.compile('\\[')),
('RBRACKET', re.compile('\\]')),
('FunctionName', re.compile('[a-zA-Z_][a-zA-Z0-9_.-]*(:[a-zA-Z_][a-zA-Z0-9_.-]*)?')),
('DOT', re.compile('\\.')),
('DOTDOT', re.compile('\\.\\.')),
('BAR', re.compile('\\|')),
('END', re.compile('#')),
('ID', re.compile('id')),
('KEY', re.compile('key')),
]
def __init__(self, str):
Scanner.__init__(self,None,[],str)
class XPath(Parser):
def Start(self):
LocationPath = self.LocationPath()
END = self._scan('END')
return LocationPath
def FullExpr(self):
Expr = self.Expr()
END = self._scan('END')
return Expr
def LocationPath(self):
_token_ = self._peek()
if _token_ in ['AxisName', 'NodeType', 'DOT', 'DOTDOT', "'@'", 'STAR', 'QName', 'NCNameStar', 'NCName']:
RelativeLocationPath = self.RelativeLocationPath()
return RelativeLocationPath
elif _token_ in ["'/'", "'//'"]:
AbsoluteLocationPath = self.AbsoluteLocationPath()
return AbsoluteLocationPath
else:
raise SyntaxError(self._pos, 'Could not match LocationPath')
def AbsoluteLocationPath(self):
_token_ = self._peek()
if _token_ == "'/'":
self._scan("'/'")
OptRelativeLocationPath = self.OptRelativeLocationPath()
return self.absoluteLocationPath(OptRelativeLocationPath)
elif _token_ == "'//'":
AbbreviatedAbsoluteLocationPath = self.AbbreviatedAbsoluteLocationPath()
return AbbreviatedAbsoluteLocationPath
else:
raise SyntaxError(self._pos, 'Could not match AbsoluteLocationPath')
def OptRelativeLocationPath(self):
_token_ = self._peek()
if _token_ not in ["'@'", "'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'ID', 'KEY']:
return None
elif _token_ not in ["'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'LPAREN', 'LBRACKET', 'FunctionName', 'ID', 'KEY']:
RelativeLocationPath = self.RelativeLocationPath()
return RelativeLocationPath
else:
raise SyntaxError(self._pos, 'Could not match OptRelativeLocationPath')
def RelativeLocationPath(self):
Step = self.Step()
RelativeLocationPaths = self.RelativeLocationPaths(Step)
return RelativeLocationPaths
def RelativeLocationPaths(self, v):
_token_ = self._peek()
if _token_ not in ["'@'", "'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'ID', 'KEY']:
return v
elif _token_ == "'/'":
self._scan("'/'")
Step = self.Step()
RelativeLocationPaths = self.RelativeLocationPaths(self.rlp(v,Step))
return RelativeLocationPaths
elif _token_ == "'//'":
self._scan("'//'")
Step = self.Step()
RelativeLocationPaths = self.RelativeLocationPaths(self.arlp(v,Step))
return RelativeLocationPaths
else:
raise SyntaxError(self._pos, 'Could not match RelativeLocationPaths')
def Step(self):
_token_ = self._peek()
if _token_ in ['AxisName', 'NodeType', "'@'", 'STAR', 'QName', 'NCNameStar', 'NCName']:
AxisSpecifier = self.AxisSpecifier()
NodeTest = self.NodeTest()
Predicates = self.Predicates()
return self.step(AxisSpecifier,NodeTest,Predicates)
elif _token_ in ['DOT', 'DOTDOT']:
AbbreviatedStep = self.AbbreviatedStep()
return AbbreviatedStep
else:
raise SyntaxError(self._pos, 'Could not match Step')
def Predicates(self):
_token_ = self._peek()
if _token_ not in ["'@'", "'::'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'ID', 'KEY']:
return []
elif _token_ == 'LBRACKET':
Predicate = self.Predicate()
Predicates = self.Predicates()
return [Predicate]+Predicates
else:
raise SyntaxError(self._pos, 'Could not match Predicates')
def AxisSpecifier(self):
_token_ = self._peek()
if _token_ == 'AxisName':
AxisName = self._scan('AxisName')
self._scan("'::'")
return self.axisSpecifier(self.anMap[AxisName])
elif _token_ in ["'@'", 'NodeType', 'STAR', 'QName', 'NCNameStar', 'NCName']:
AbbreviatedAxisSpecifier = self.AbbreviatedAxisSpecifier()
return AbbreviatedAxisSpecifier
else:
raise SyntaxError(self._pos, 'Could not match AxisSpecifier')
def NodeTest(self):
_token_ = self._peek()
if _token_ in ['STAR', 'QName', 'NCNameStar', 'NCName']:
NameTest = self.NameTest()
return NameTest
elif _token_ == 'NodeType':
NodeType = self._scan('NodeType')
LPAREN = self._scan('LPAREN')
OptLiteral = self.OptLiteral()
RPAREN = self._scan('RPAREN')
return self.mkNodeTest(NodeType,OptLiteral)
else:
raise SyntaxError(self._pos, 'Could not match NodeTest')
def OptLiteral(self):
_token_ = self._peek()
if _token_ == 'RPAREN':
return None
elif _token_ == 'Literal':
Literal = self._scan('Literal')
return Literal
else:
raise SyntaxError(self._pos, 'Could not match OptLiteral')
def NameTest(self):
_token_ = self._peek()
if _token_ == 'STAR':
STAR = self._scan('STAR')
return self.nameTest(None,"*")
elif _token_ == 'QName':
QName = self._scan('QName')
return self.mkQName(QName)
elif _token_ == 'NCNameStar':
NCNameStar = self._scan('NCNameStar')
return self.nameTest(NCNameStar[:-2],'*')
elif _token_ == 'NCName':
NCName = self._scan('NCName')
return self.nameTest(None,NCName)
else:
raise SyntaxError(self._pos, 'Could not match NameTest')
def Predicate(self):
LBRACKET = self._scan('LBRACKET')
PredicateExpr = self.PredicateExpr()
RBRACKET = self._scan('RBRACKET')
return PredicateExpr
def PredicateExpr(self):
Expr = self.Expr()
return Expr
def AbbreviatedAbsoluteLocationPath(self):
self._scan("'//'")
RelativeLocationPath = self.RelativeLocationPath()
return self.aalp(RelativeLocationPath)
def AbbreviatedStep(self):
_token_ = self._peek()
if _token_ == 'DOT':
DOT = self._scan('DOT')
return self.abbreviatedStep(0)
elif _token_ == 'DOTDOT':
DOTDOT = self._scan('DOTDOT')
return self.abbreviatedStep(1)
else:
raise SyntaxError(self._pos, 'Could not match AbbreviatedStep')
def AbbreviatedAxisSpecifier(self):
_token_ = self._peek()
if _token_ in ['NodeType', 'STAR', 'QName', 'NCNameStar', 'NCName']:
return self.axisSpecifier(pyxpath.CHILD_AXIS)
elif _token_ == "'@'":
self._scan("'@'")
return self.axisSpecifier(pyxpath.ATTRIBUTE_AXIS)
else:
raise SyntaxError(self._pos, 'Could not match AbbreviatedAxisSpecifier')
def Expr(self):
OrExpr = self.OrExpr()
return OrExpr
def PrimaryExpr(self):
_token_ = self._peek()
if _token_ == 'VariableReference':
VariableReference = self._scan('VariableReference')
return self.mkVariableReference(VariableReference)
elif _token_ == 'LPAREN':
LPAREN = self._scan('LPAREN')
Expr = self.Expr()
RPAREN = self._scan('RPAREN')
return Expr
elif _token_ == 'Literal':
Literal = self._scan('Literal')
return self.literal(Literal)
elif _token_ == 'Number':
Number = self._scan('Number')
return self.number(Number)
elif _token_ in ['FunctionName', 'ID', 'KEY']:
FunctionCall = self.FunctionCall()
return FunctionCall
else:
raise SyntaxError(self._pos, 'Could not match PrimaryExpr')
def FunctionCall(self):
_token_ = self._peek()
if _token_ == 'FunctionName':
FunctionName = self._scan('FunctionName')
LPAREN = self._scan('LPAREN')
Arguments = self.Arguments()
RPAREN = self._scan('RPAREN')
return self.mkFunctionCall(FunctionName,Arguments)
elif _token_ == 'ID':
ID = self._scan('ID')
LPAREN = self._scan('LPAREN')
Arguments = self.Arguments()
RPAREN = self._scan('RPAREN')
return self.functionCall(None,'id',Arguments)
elif _token_ == 'KEY':
KEY = self._scan('KEY')
LPAREN = self._scan('LPAREN')
Arguments = self.Arguments()
RPAREN = self._scan('RPAREN')
return self.functionCall(None,'key',Arguments)
else:
raise SyntaxError(self._pos, 'Could not match FunctionCall')
def Arguments(self):
_token_ = self._peek()
if _token_ == 'RPAREN':
return []
elif _token_ not in ["'mod'", "'div'", "'>='", "'>'", "'<='", "'<'", "'!='", "'='", "'and'", "'or'", "','", "'::'", 'MultiplyOperator', 'PLUS', 'LBRACKET', 'RBRACKET', 'BAR', 'END']:
Argument = self.Argument()
KommaArguments = self.KommaArguments([Argument])
return KommaArguments
else:
raise SyntaxError(self._pos, 'Could not match Arguments')
def KommaArguments(self, v):
_token_ = self._peek()
if _token_ == 'RPAREN':
return v
elif _token_ == "','":
self._scan("','")
Argument = self.Argument()
KommaArguments = self.KommaArguments(v+[Argument])
return KommaArguments
else:
raise SyntaxError(self._pos, 'Could not match KommaArguments')
def Argument(self):
Expr = self.Expr()
return Expr
def UnionExpr(self):
PathExpr = self.PathExpr()
UnionExprs = self.UnionExprs(PathExpr)
return UnionExprs
def UnionExprs(self, v):
_token_ = self._peek()
if _token_ not in ["'@'", "'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'BAR', 'ID', 'KEY']:
return v
elif _token_ == 'BAR':
BAR = self._scan('BAR')
PathExpr = self.PathExpr()
UnionExprs = self.UnionExprs(self.nop(self.UNION,v,PathExpr))
return UnionExprs
else:
raise SyntaxError(self._pos, 'Could not match UnionExprs')
def PathExpr(self):
_token_ = self._peek()
if _token_ in ["'/'", "'//'", 'AxisName', 'NodeType', 'DOT', 'DOTDOT', "'@'", 'STAR', 'QName', 'NCNameStar', 'NCName']:
LocationPath = self.LocationPath()
return LocationPath
elif _token_ in ['VariableReference', 'LPAREN', 'Literal', 'Number', 'FunctionName', 'ID', 'KEY']:
FilterExpr = self.FilterExpr()
PathExprRest = self.PathExprRest(FilterExpr)
return PathExprRest
else:
raise SyntaxError(self._pos, 'Could not match PathExpr')
def PathExprRest(self, v):
_token_ = self._peek()
if _token_ not in ["'@'", "'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'ID', 'KEY']:
return v
elif _token_ == "'/'":
self._scan("'/'")
RelativeLocationPath = self.RelativeLocationPath()
return self.pathExpr(v,RelativeLocationPath)
elif _token_ == "'//'":
self._scan("'//'")
RelativeLocationPath = self.RelativeLocationPath()
return self.abbreviatedPathExpr(v,RelativeLocationPath)
else:
raise SyntaxError(self._pos, 'Could not match PathExprRest')
def FilterExpr(self):
PrimaryExpr = self.PrimaryExpr()
FilterExprs = self.FilterExprs(PrimaryExpr)
return FilterExprs
def FilterExprs(self, v):
_token_ = self._peek()
if _token_ not in ["'@'", "'::'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'ID', 'KEY']:
return v
elif _token_ == 'LBRACKET':
Predicate = self.Predicate()
e=[Predicate]
while self._peek() == 'LBRACKET':
Predicate = self.Predicate()
e.append(Predicate)
return self.filterExpr(v,e)
else:
raise SyntaxError(self._pos, 'Could not match FilterExprs')
def OrExpr(self):
AndExpr = self.AndExpr()
OrExprs = self.OrExprs(AndExpr)
return OrExprs
def OrExprs(self, v):
_token_ = self._peek()
if _token_ == "'or'":
self._scan("'or'")
AndExpr = self.AndExpr()
OrExprs = self.OrExprs(self.bop(self.OR,v,AndExpr))
return OrExprs
elif _token_ in ['END', 'RPAREN', 'RBRACKET', "','"]:
return v
else:
raise SyntaxError(self._pos, 'Could not match OrExprs')
def AndExpr(self):
EqualityExpr = self.EqualityExpr()
AndExprs = self.AndExprs(EqualityExpr)
return AndExprs
def AndExprs(self, v):
_token_ = self._peek()
if _token_ == "'and'":
self._scan("'and'")
EqualityExpr = self.EqualityExpr()
AndExprs = self.AndExprs(self.bop(self.AND,v,EqualityExpr))
return AndExprs
elif _token_ in ["'or'", 'END', 'RPAREN', 'RBRACKET', "','"]:
return v
else:
raise SyntaxError(self._pos, 'Could not match AndExprs')
def EqualityExpr(self):
RelationalExpr = self.RelationalExpr()
EqualityExprs = self.EqualityExprs(RelationalExpr)
return EqualityExprs
def EqualityExprs(self, v):
_token_ = self._peek()
if _token_ == "'='":
self._scan("'='")
RelationalExpr = self.RelationalExpr()
EqualityExprs = self.EqualityExprs(self.bop(self.EQ,v,RelationalExpr))
return EqualityExprs
elif _token_ == "'!='":
self._scan("'!='")
RelationalExpr = self.RelationalExpr()
EqualityExprs = self.EqualityExprs(self.bop(self.NEQ,v,RelationalExpr))
return EqualityExprs
elif _token_ in ["'and'", "'or'", 'END', 'RPAREN', 'RBRACKET', "','"]:
return v
else:
raise SyntaxError(self._pos, 'Could not match EqualityExprs')
def RelationalExpr(self):
AdditiveExpr = self.AdditiveExpr()
RelationalExprs = self.RelationalExprs(AdditiveExpr)
return RelationalExprs
def RelationalExprs(self, v):
_token_ = self._peek()
if _token_ == "'<'":
self._scan("'<'")
AdditiveExpr = self.AdditiveExpr()
RelationalExprs = self.RelationalExprs(self.bop(self.LT,v,AdditiveExpr))
return RelationalExprs
elif _token_ == "'<='":
self._scan("'<='")
AdditiveExpr = self.AdditiveExpr()
RelationalExprs = self.RelationalExprs(self.bop(self.LE,v,AdditiveExpr))
return RelationalExprs
elif _token_ == "'>'":
self._scan("'>'")
AdditiveExpr = self.AdditiveExpr()
RelationalExprs = self.RelationalExprs(self.bop(self.GT,v,AdditiveExpr))
return RelationalExprs
elif _token_ == "'>='":
self._scan("'>='")
AdditiveExpr = self.AdditiveExpr()
RelationalExprs = self.RelationalExprs(self.bop(self.GE,v,AdditiveExpr))
return RelationalExprs
elif _token_ in ["'='", "'!='", "'and'", "'or'", 'END', 'RPAREN', 'RBRACKET', "','"]:
return v
else:
raise SyntaxError(self._pos, 'Could not match RelationalExprs')
def AdditiveExpr(self):
MultiplicativeExpr = self.MultiplicativeExpr()
AdditiveExprs = self.AdditiveExprs(MultiplicativeExpr)
return AdditiveExprs
def AdditiveExprs(self, v):
_token_ = self._peek()
if _token_ == 'PLUS':
PLUS = self._scan('PLUS')
MultiplicativeExpr = self.MultiplicativeExpr()
AdditiveExprs = self.AdditiveExprs(self.nop(self.PLUS,v,MultiplicativeExpr))
return AdditiveExprs
elif _token_ == "'-'":
self._scan("'-'")
MultiplicativeExpr = self.MultiplicativeExpr()
AdditiveExprs = self.AdditiveExprs(self.nop(self.MINUS,v,MultiplicativeExpr))
return AdditiveExprs
elif _token_ in ["'<'", "'<='", "'>'", "'>='", "'='", "'!='", "'and'", "'or'", 'END', 'RPAREN', 'RBRACKET', "','"]:
return v
else:
raise SyntaxError(self._pos, 'Could not match AdditiveExprs')
def MultiplicativeExpr(self):
UnaryExpr = self.UnaryExpr()
MultiplicativeExprs = self.MultiplicativeExprs(UnaryExpr)
return MultiplicativeExprs
def MultiplicativeExprs(self, v):
_token_ = self._peek()
if _token_ == 'MultiplyOperator':
MultiplyOperator = self._scan('MultiplyOperator')
UnaryExpr = self.UnaryExpr()
MultiplicativeExprs = self.MultiplicativeExprs(self.nop(self.TIMES,v,UnaryExpr))
return MultiplicativeExprs
elif _token_ == "'div'":
self._scan("'div'")
UnaryExpr = self.UnaryExpr()
MultiplicativeExprs = self.MultiplicativeExprs(self.nop(self.DIV,v,UnaryExpr))
return MultiplicativeExprs
elif _token_ == "'mod'":
self._scan("'mod'")
UnaryExpr = self.UnaryExpr()
MultiplicativeExprs = self.MultiplicativeExprs(self.nop(self.MOD,v,UnaryExpr))
return MultiplicativeExprs
elif _token_ not in ["'@'", "'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'BAR', 'ID', 'KEY']:
return v
else:
raise SyntaxError(self._pos, 'Could not match MultiplicativeExprs')
def UnaryExpr(self):
_token_ = self._peek()
if _token_ == "'-'":
self._scan("'-'")
UnaryExpr = self.UnaryExpr()
return self.unaryExpr(UnaryExpr)
elif _token_ not in ["'mod'", "'div'", "'>='", "'>'", "'<='", "'<'", "'!='", "'='", "'and'", "'or'", "','", "'::'", 'MultiplyOperator', 'RPAREN', 'PLUS', 'LBRACKET', 'RBRACKET', 'BAR', 'END']:
UnionExpr = self.UnionExpr()
return UnionExpr
else:
raise SyntaxError(self._pos, 'Could not match UnaryExpr')
def FullPattern(self):
Pattern = self.Pattern()
END = self._scan('END')
return Pattern
def Pattern(self):
LocationPathPattern = self.LocationPathPattern()
p = self.pattern(LocationPathPattern)
while self._peek() == 'BAR':
BAR = self._scan('BAR')
LocationPathPattern = self.LocationPathPattern()
p.append(LocationPathPattern)
return p
def LocationPathPattern(self):
_token_ = self._peek()
if _token_ == "'/'":
self._scan("'/'")
OptRelativePathPattern = self.OptRelativePathPattern()
return self.locationPathPattern(None,1,OptRelativePathPattern)
elif _token_ in ['ID', 'KEY']:
IdKeyPattern = self.IdKeyPattern()
IdTail = self.IdTail()
return self.locationPathPattern(IdKeyPattern,IdTail[0],IdTail[1])
elif _token_ in ['NodeType', "'@'", 'AxisName', 'STAR', 'QName', 'NCNameStar', 'NCName']:
RelativePathPattern = self.RelativePathPattern()
return RelativePathPattern
elif _token_ == "'//'":
self._scan("'//'")
RelativePathPattern = self.RelativePathPattern()
return self.locationPathPattern(None,0,RelativePathPattern)
else:
raise SyntaxError(self._pos, 'Could not match LocationPathPattern')
def OptRelativePathPattern(self):
_token_ = self._peek()
if _token_ in ['BAR', 'END']:
return None
elif _token_ in ['NodeType', "'@'", 'AxisName', 'STAR', 'QName', 'NCNameStar', 'NCName']:
RelativePathPattern = self.RelativePathPattern()
return RelativePathPattern
else:
raise SyntaxError(self._pos, 'Could not match OptRelativePathPattern')
def IdTail(self):
_token_ = self._peek()
if _token_ in ['BAR', 'END']:
return (0,None)
elif _token_ == "'/'":
self._scan("'/'")
RelativePathPattern = self.RelativePathPattern()
return (1,RelativePathPattern)
elif _token_ == "'//'":
self._scan("'//'")
RelativePathPattern = self.RelativePathPattern()
return (0,RelativePathPattern)
else:
raise SyntaxError(self._pos, 'Could not match IdTail')
def IdKeyPattern(self):
_token_ = self._peek()
if _token_ == 'ID':
ID = self._scan('ID')
LPAREN = self._scan('LPAREN')
Argument = self.Argument()
RPAREN = self._scan('RPAREN')
return self.functionCall(None,"id", [Argument])
elif _token_ == 'KEY':
KEY = self._scan('KEY')
LPAREN = self._scan('LPAREN')
Argument = self.Argument()
a1=Argument
self._scan("','")
Argument = self.Argument()
RPAREN = self._scan('RPAREN')
return self.functionCall(None,"key", [a1,Argument])
else:
raise SyntaxError(self._pos, 'Could not match IdKeyPattern')
def RelativePathPattern(self):
StepPattern = self.StepPattern()
p=StepPattern
while self._peek() in ["'/'", "'//'"]:
_token_ = self._peek()
if _token_ == "'/'":
self._scan("'/'")
StepPattern = self.StepPattern()
p=self.rpp(p, 1, StepPattern)
elif _token_ == "'//'":
self._scan("'//'")
StepPattern = self.StepPattern()
p=self.rpp(p, 0, StepPattern)
else:
raise SyntaxError(self._pos, 'Could not match RelativePathPattern')
return p
def StepPattern(self):
ChildOrAttributeAxisSpecifier = self.ChildOrAttributeAxisSpecifier()
NodeTest = self.NodeTest()
pred=[]
while self._peek() == 'LBRACKET':
Predicate = self.Predicate()
pred.append(Predicate)
return self.stepPattern(ChildOrAttributeAxisSpecifier,NodeTest,pred)
def ChildOrAttributeAxisSpecifier(self):
_token_ = self._peek()
if _token_ in ["'@'", 'NodeType', 'STAR', 'QName', 'NCNameStar', 'NCName']:
AbbreviatedAxisSpecifier = self.AbbreviatedAxisSpecifier()
return AbbreviatedAxisSpecifier
elif _token_ == 'AxisName':
AxisName = self._scan('AxisName')
self._scan("'::'")
return self.axisSpecifier(self.anMap[AxisName])
else:
raise SyntaxError(self._pos, 'Could not match ChildOrAttributeAxisSpecifier')
def parse(rule, text):
P = XPath(XPathScanner(text))
return wrap_error_reporter(P, rule)
# Reimplement scanner, to properly use disambiguation
import re, sys
NCName = "[a-zA-Z_](\w|[_.-])*"
# In this version of QName, the namespace prefix is not optional.
# As a result, QName matches iff there is a colon, NCName otherwise.
# All appearances of QName in the grammar then need to allow NCName
# as an alternative; currently, QName is used only once.
QName = NCName + ":" + NCName
XPathExpr="""
(?P<Literal>\"[^\"]*\"|\'[^\']*\')|
(?P<Number>\\d+(\\.\\d*)?|\\.\\d+)|
(?P<VariableReference>\\$""" + NCName + "(:" + NCName + """)?)|
(?P<QName>"""+QName+""")|
(?P<NCNameStar>"""+NCName+""":\*)|
(?P<NCName>"""+NCName+""")|
(?P<LPAREN>\\()|
(?P<RPAREN>\\))|
(?P<STAR>\\*)|
(?P<PLUS>\\+)|
(?P<LBRACKET>\\[)|
(?P<RBRACKET>\\])|
(?P<DOTDOT>\\.\\.)|
(?P<DOT>\\.)|
(?P<BAR>\\|)|
(?P<Operator>//|::|>=|<=|!=)|
(?P<SingleOperator>[<>=,/@:-])|
(?P<ExprWhiteSpace>[ \t\n\r]+)
"""
_xpath_exp = re.compile(XPathExpr,re.VERBOSE)
OperatorName = ['and','or','mod','div']
AxisName = ['ancestor', 'ancestor-or-self', 'attribute', 'child',
'descendant', 'descendant-or-self', 'following',
'following-sibling', 'namespace', 'parent', 'preceding',
'preceding-sibling', 'self']
SpecialPreceding = map(repr,["@","::","(","["] + OperatorName + ['/', '//', '+', '-', '=', '!=', '<', '<=', '>', '>=']) + ["BAR","MultiplyOperator"]
if sys.hexversion > 0x2000000:
def _get_type(match):
return match.lastgroup,match.group()
else:
def _get_type(match):
type = val = None
for t,v in match.groupdict().items():
if v is None: continue
if val:
raise SyntaxError(pos,
"ambiguity:%s could be %s or %s" % (val,type,t))
type = t
val = v
return type,val
class XPathScanner:
def __init__(self,input):
self.tokens = tokens = []
pos = 0
# Process all tokens, advancing pos for each one
while pos != len(input):
m = _xpath_exp.match(input, pos)
if not m:
msg = "Bad Token"
raise SyntaxError(pos, msg)
type, val = _get_type(m)
if type == "ExprWhiteSpace":
# If we got white space, ignore it
pos = pos + len(val)
continue
if type in ['SingleOperator', 'Operator']:
type = repr(str(val))
start = pos
pos = pos + len(val)
tokens.append((start, pos, type, val))
# If we are at the end of the string, add END token
tokens.append((pos,pos,'END',""))
# Adjust token type according to additional semantic rules
for i in range(len(tokens)-1):
start,stop,type,val = tokens[i]
changed = 0
# If there is a preceding token and the preceding token is not
# one of @, ::, (, [, , or an Operator
if i>=1 and tokens[i-1][2] not in SpecialPreceding:
if type == 'STAR':
# then a * must be recognized as a MultiplyOperator
type = 'MultiplyOperator'
tokens[i] = (start,stop,type,val)
elif type == 'NCName' and val in OperatorName:
# and an NCName must be recognized as an OperatorName
type = repr(str(val))
tokens[i] = (start,stop,type,val)
# If the character following an NCName (possibly after
# intervening ExprWhitespace) is (
if tokens[i][2] in ['QName','NCName'] and tokens[i+1][2]=='LPAREN':
# then the token must be recognized as a NodeType or a
# FunctionName
if val in ['comment','text','processing-instruction','node']:
type = 'NodeType'
elif val == 'id':
type = 'ID'
elif val == 'key':
type = 'KEY'
else:
type = 'FunctionName'
tokens[i] = (start,stop,type,val)
# If the two characters following an NCName (possibly
# after intervening ExprWhitespace) are ::
if tokens[i][2] == 'NCName' and tokens[i+1][3]=='::' \
and val in AxisName:
# then the token must be recognized as an AxisName.
type = 'AxisName'
tokens[i] = (start,stop,type,val)
def token(self, i, expected):
return self.tokens[i]
# redefine to add additional attributes
import pyxpath,string
GeneratedXPath = XPath
class XPath(GeneratedXPath):
OR = pyxpath.OR_OPERATOR
AND = pyxpath.AND_OPERATOR
EQ = pyxpath.EQ_OPERATOR
NEQ = pyxpath.NEQ_OPERATOR
LT = pyxpath.LT_OPERATOR
GT = pyxpath.GT_OPERATOR
LE = pyxpath.LE_OPERATOR
GE = pyxpath.GE_OPERATOR
PLUS = pyxpath.PLUS_OPERATOR
MINUS = pyxpath.MINUS_OPERATOR
TIMES = pyxpath.TIMES_OPERATOR
DIV = pyxpath.DIV_OPERATOR
MOD = pyxpath.MOD_OPERATOR
UNION = pyxpath.UNION_OPERATOR
def __init__(self, scanner, factory):
GeneratedXPath.__init__(self, scanner)
self.factory = factory
# shorthands
self.rlp = self.factory.createRelativeLocationPath
self.arlp = self.factory.createAbbreviatedRelativeLocationPath
self.aalp = self.factory.createAbbreviatedAbsoluteLocationPath
self.nop = self.factory.createNumericExpr
self.bop = self.factory.createBooleanExpr
self.rpp = self.factory.createRelativePathPattern
def __getattr__(self, name):
# convert
newname = "create"+string.upper(name[0])+name[1:]
try:
return getattr(self.factory, newname)
except AttributeError:
raise AttributeError,"parser has no attribute "+name
anMap = {
'ancestor':pyxpath.ANCESTOR_AXIS,
'ancestor-or-self':pyxpath.ANCESTOR_OR_SELF_AXIS,
'attribute':pyxpath.ATTRIBUTE_AXIS,
'child':pyxpath.CHILD_AXIS,
'descendant':pyxpath.DESCENDANT_AXIS,
'descendant-or-self':pyxpath.DESCENDANT_OR_SELF_AXIS,
'following':pyxpath.FOLLOWING_AXIS,
'following-sibling':pyxpath.FOLLOWING_SIBLING_AXIS,
'namespace':pyxpath.NAMESPACE_AXIS,
'parent':pyxpath.PARENT_AXIS,
'preceding':pyxpath.PRECEDING_AXIS,
'preceding-sibling':pyxpath.PRECEDING_SIBLING_AXIS,
'self':pyxpath.SELF_AXIS
}
nodeTestMap = {
'node': pyxpath.NODE,
'comment': pyxpath.COMMENT,
'text': pyxpath.TEXT,
'processing-instruction': pyxpath.PROCESSING_INSTRUCTION
}
def mkNodeTest(self,op,val):
type = self.nodeTestMap[op]
if type != pyxpath.PROCESSING_INSTRUCTION and val is not None:
raise SyntaxError("parameter not allowed for "+op)
return self.factory.createNodeTest(type,val)
def mkQName(self,str):
prefix,local = string.split(str,":")
return self.factory.createNameTest(prefix,local)
def mkVariableReference(self, qname):
colon = string.find(qname,':')
if colon == -1:
return self.variableReference(None, qname[1:])
return self.variableReference(qname[1:colon],qname[colon+1:])
def mkFunctionCall(self, qname, args):
colon = string.find(qname,':')
if colon == -1:
return self.functionCall(None, qname, args)
return self.functionCall(qname[:colon],qname[colon+1:],args)