xpathparser.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,355 行 · 第 1/3 页
JAVA
1,355 行
int ch = skipWhitespace(read()); AbstractPattern tagPattern; if (ch == '(') { Expr expr = parseFunction(pattern, pattern, name, fromChildren); return expr.toNodeList(); } else if (ch == '{') { tag.clear(); while ((ch = read()) >= 0 && ch != '}') tag.append((char) ch); String url = tag.toString(); tag.clear(); for (ch = read(); XmlChar.isNameChar(ch); ch = read()) tag.append((char) ch); pattern = new NSNamePattern(pattern, url, tag.toString(), nodeType); } else { if (fromChildren) pattern = new FromChildren(pattern); if (name.equals("*")) pattern = NodeTypePattern.create(pattern, nodeType); else if (name.endsWith(":*")) { pattern = new NamespacePattern(pattern, name.substring(0, name.length() - 2), nodeType); } else { int p = name.indexOf(':'); String ns = null; String local = name; if (p > 0) { String prefix = name.substring(0, p); ns = NamespaceContext.find(_namespace, prefix); local = name.substring(p + 1); } else if (nodeType != Node.ATTRIBUTE_NODE) ns = _namespace.find(_namespace, ""); else ns = null; // _namespace.find(_namespace, ""); if (ns == null) pattern = new NodePattern(pattern, name, nodeType); else pattern = new NSNamePattern(pattern, ns, local, nodeType); } } unread(); return pattern; } /** * expr ::= or-expr */ Expr parseExpr(AbstractPattern parent, AbstractPattern listParent) throws XPathParseException { peek = -1; Expr left = parseTerm(parent, listParent); while (true) { int token = scanToken(); switch (token) { case Expr.OR: left = parseOrExpr(token, left, parseTerm(parent, listParent), parent, listParent); break; case Expr.AND: left = parseAndExpr(token, left, parseTerm(parent, listParent), parent, listParent); break; case Expr.EQ: case Expr.NEQ: case Expr.LT: case Expr.LE: case Expr.GT: case Expr.GE: left = parseCmpExpr(token, left, parseTerm(parent, listParent), parent, listParent); break; case Expr.ADD: case Expr.SUB: left = parseAddExpr(token, left, parseTerm(parent, listParent), parent, listParent); break; case Expr.MUL: case Expr.DIV: case Expr.QUO: case Expr.MOD: left = parseMulExpr(token, left, parseTerm(parent, listParent), parent, listParent); break; default: return left; } } } /** * or-expr ::= or-expr 'OR' expr * | and-expr */ private Expr parseOrExpr(int code, Expr left, Expr right, AbstractPattern parent, AbstractPattern listParent) throws XPathParseException { while (true) { int token = scanToken(); switch (token) { case Expr.OR: left = new BooleanExpr(code, left, right); code = token; right = parseTerm(parent, listParent); break; case Expr.AND: right = parseAndExpr(token, right, parseTerm(parent, listParent), parent, listParent); break; case Expr.EQ: case Expr.NEQ: case Expr.LT: case Expr.LE: case Expr.GT: case Expr.GE: right = parseCmpExpr(token, right, parseTerm(parent, listParent), parent, listParent); break; case Expr.ADD: case Expr.SUB: right = parseAddExpr(token, right, parseTerm(parent, listParent), parent, listParent); break; case Expr.MUL: case Expr.DIV: case Expr.QUO: case Expr.MOD: right = parseMulExpr(token, right, parseTerm(parent, listParent), parent, listParent); break; default: undoToken(token); return new BooleanExpr(code, left, right); } } } /** * and-expr ::= and-expr 'AND' expr * | cmp-expr */ private Expr parseAndExpr(int code, Expr left, Expr right, AbstractPattern parent, AbstractPattern listParent) throws XPathParseException { while (true) { int token = scanToken(); switch (token) { case Expr.AND: left = new BooleanExpr(code, left, right); code = token; right = parseTerm(parent, listParent); break; case Expr.EQ: case Expr.NEQ: case Expr.LT: case Expr.LE: case Expr.GT: case Expr.GE: right = parseCmpExpr(token, right, parseTerm(parent, listParent), parent, listParent); break; case Expr.ADD: case Expr.SUB: right = parseAddExpr(token, right, parseTerm(parent, listParent), parent, listParent); break; case Expr.MUL: case Expr.DIV: case Expr.QUO: case Expr.MOD: right = parseMulExpr(token, right, parseTerm(parent, listParent), parent, listParent); break; default: undoToken(token); return new BooleanExpr(code, left, right); } } } /** * cmp-expr ::= cmp-expr '<' expr * | add-expr */ private Expr parseCmpExpr(int code, Expr left, Expr right, AbstractPattern parent, AbstractPattern listParent) throws XPathParseException { while (true) { int token = scanToken(); switch (token) { case Expr.EQ: case Expr.NEQ: case Expr.LT: case Expr.LE: case Expr.GT: case Expr.GE: left = new BooleanExpr(code, left, right); code = token; right = parseTerm(parent, listParent); break; case Expr.ADD: case Expr.SUB: right = parseAddExpr(token, right, parseTerm(parent, listParent), parent, listParent); break; case Expr.MUL: case Expr.DIV: case Expr.QUO: case Expr.MOD: right = parseMulExpr(token, right, parseTerm(parent, listParent), parent, listParent); break; default: undoToken(token); return new BooleanExpr(code, left, right); } } } /** * add-expr ::= add-expr '+' expr * | mul-expr */ private Expr parseAddExpr(int code, Expr left, Expr right, AbstractPattern parent, AbstractPattern listParent) throws XPathParseException { while (true) { int token = scanToken(); switch (token) { case Expr.ADD: case Expr.SUB: left = new NumericExpr(code, left, right); code = token; right = parseTerm(parent, listParent); break; case Expr.MUL: case Expr.DIV: case Expr.QUO: case Expr.MOD: right = parseMulExpr(token, right, parseTerm(parent, listParent), parent, listParent); break; default: undoToken(token); return new NumericExpr(code, left, right); } } } /** * mul-expr ::= mul-expr '*' expr * | term */ private Expr parseMulExpr(int code, Expr left, Expr right, AbstractPattern parent, AbstractPattern listParent) throws XPathParseException { while (true) { int token = scanToken(); switch (token) { case Expr.MUL: case Expr.DIV: case Expr.QUO: case Expr.MOD: left = new NumericExpr(code, left, right); code = token; right = parseTerm(parent, listParent); break; default: undoToken(token); return new NumericExpr(code, left, right); } } } /** * term ::= simple-term path? */ private Expr parseTerm(AbstractPattern parent, AbstractPattern listParent) throws XPathParseException { int ch = skipWhitespace(read()); unread(); Expr expr = parseSimpleTerm(parent, listParent); int nextCh = skipWhitespace(read()); unread(); if (nextCh == '/' || nextCh == '[') { AbstractPattern pattern = expr.toNodeList(); if (ch == '(' && ! pattern.isStrictlyAscending()) pattern = new FromExpr(null, expr); return NodeSetExpr.create(parseUnion(parsePath(parseFilter(pattern)), pattern)); } else if (nextCh == '|') { AbstractPattern pattern = expr.toNodeList(); return NodeSetExpr.create(parseUnion(parsePath(parseFilter(pattern)), listParent)); } else return expr; } /** * simple-term ::= number * ::= '(' expr ')' * ::= '$' variable * ::= '"' string '"' * ::= node-set */ private Expr parseSimpleTerm(AbstractPattern parent, AbstractPattern listParent) throws XPathParseException { int ch = read(); ch = skipWhitespace(ch); switch (ch) { case '.': ch = read(); unread(); unread(); if (! ('0' <= ch && ch <= '9')) { return NodeSetExpr.create(parseUnion(parseBasisTop(parent), parent)); } ch = read(); // fall through to parse the number case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { long value = 0; double exp = 1; int digits = 0; for (; ch >= '0' && ch <= '9'; ch = read()) value = 10 * value + ch - '0'; if (ch == '.') { for (ch = read(); ch >= '0' && ch <= '9'; ch = read()) { value = 10 * value + ch - '0'; exp *= 10; digits--; } } if (ch == 'e' || ch == 'E') { int sign = 1; int expValue = 0; ch = read(); if (ch == '-') { sign = -1; ch = read(); } else if (ch == '+') ch = read(); for (; ch >= '0' && ch <= '9'; ch = read()) expValue = 10 * expValue + ch - '0'; exp = Math.pow(10, digits + sign * expValue); unread(); return new NumericExpr((double) value * (double) exp); } unread(); return new NumericExpr((double) value / (double) exp); } case '-': return new NumericExpr(Expr.NEG, parseTerm(parent, listParent)); case '+': return parseTerm(parent, listParent); case '(': { Expr expr = parseExpr(parent, listParent); if ((ch = skipWhitespace(read())) != ')') throw error(L.l("expected `{0}' at {1}", ")", badChar(ch))); return expr; } case '/': case '@': case '*': unread(); return NodeSetExpr.create(parseUnion(parseBasisTop(parent), parent)); case '\'': case '"': { int end = ch; CharBuffer cb = new CharBuffer(); for (ch = read(); ch >= 0; ch = read()) { if (ch != end) cb.append((char) ch); else if ((ch = read()) == end) cb.append((char) ch); else { unread(); break; } } return new StringExpr(cb.toString()); } case '$': { String name = readName(read()); return new VarExpr(name); } default: if (! XmlChar.isNameStart(ch)) throw error(L.l("unknown character at {0}", badChar(ch))); String name = readName(ch); ch = skipWhitespace(read()); int axisIndex = name.indexOf("::"); // make sure axis are treated as node sets if (ch == '(' && axisIndex < 0) { return parseFunction(parent, listParent, name, true); } else if (ch == '(') { String axis = name.substring(0, axisIndex); if (axisMap.get(axis) <= 0) return parseFunction(parent, listParent, name, true); } unread(); if (parent == null) parent = new FromContext(); return parseNodeSetExpr(parent, name, Node.ELEMENT_NODE); } } /** * function ::= name '(' args ')' * * The XPath library functions are hard-coded for a little extra * execution efficiency. */ Expr parseFunction(AbstractPattern parent, AbstractPattern listParent, String name, boolean fromChildren) throws XPathParseException
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?