From 6fbbe538489a912c60a47283bbf993fa071aa344 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Fri, 16 Sep 2016 01:33:32 +0000 Subject: [PATCH] impl obj ref parsing git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/exprs@1038 f203690c-595d-4dc9-a70b-905162fa7fd2 --- .../jackcess/util/ExpressionTokenizer.java | 4 + .../jackcess/util/Expressionator.java | 112 ++++++++++++++---- 2 files changed, 94 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/healthmarketscience/jackcess/util/ExpressionTokenizer.java b/src/main/java/com/healthmarketscience/jackcess/util/ExpressionTokenizer.java index 60d6f3f..b55f674 100644 --- a/src/main/java/com/healthmarketscience/jackcess/util/ExpressionTokenizer.java +++ b/src/main/java/com/healthmarketscience/jackcess/util/ExpressionTokenizer.java @@ -482,6 +482,10 @@ class ExpressionTokenizer return _val; } + public String getValueStr() { + return (String)_val; + } + @Override public String toString() { if(_type == TokenType.SPACE) { diff --git a/src/main/java/com/healthmarketscience/jackcess/util/Expressionator.java b/src/main/java/com/healthmarketscience/jackcess/util/Expressionator.java index 0fd88c5..5621cbc 100644 --- a/src/main/java/com/healthmarketscience/jackcess/util/Expressionator.java +++ b/src/main/java/com/healthmarketscience/jackcess/util/Expressionator.java @@ -153,13 +153,30 @@ public class Expressionator switch(t.getType()) { case OBJ_NAME: + + buf.setPendingExpr(parseObjectReference(t, buf)); break; + case LITERAL: + + buf.setPendingExpr(new ELiteralValue(t.getValue())); break; + case OP: + + WordType wordType = getWordType(t); + if(wordType == null) { + // shouldn't happen + throw new RuntimeException("Invalid operator " + t); + } + + break; + case STRING: - WordType wordType = getWordType(t); + + // see if it's a special word? + wordType = getWordType(t); if(wordType == null) { // literal string? or possibly function? Expr funcExpr = maybeParseFuncCall(t, buf, exprType, isSimpleExpr); @@ -167,25 +184,68 @@ public class Expressionator buf.setPendingExpr(funcExpr); continue; } + + // FIXME maybe obj name, maybe string? + + } else { + + // FIXME } + break; + case SPACE: - // top-level space is irrelevant + // top-level space is irrelevant (and we strip them anyway) break; + default: - throw new RuntimeException("unknown token type " + t.getType()); + throw new RuntimeException("unknown token type " + t); } } Expr expr = buf.takePendingExpr(); if(expr == null) { - throw new IllegalArgumentException("No expression found?"); + throw new IllegalArgumentException("No expression found? " + buf); } return expr; } + private static Expr parseObjectReference(Token firstTok, TokBuf buf) { + + // object references may be joined by '.' or '!'; + List objNames = new ArrayList(); + objNames.add(firstTok.getValueStr()); + + Token t = null; + boolean atSep = false; + while((t = buf.peekNext()) != null) { + if(!atSep) { + if(isOp(t, ".") || isOp(t, "!")) { + buf.next(); + atSep = true; + continue; + } + } else { + if((t.getType() == TokenType.OBJ_NAME) || + (t.getType() == TokenType.STRING)) { + buf.next(); + objNames.add(t.getValueStr()); + atSep = false; + continue; + } + } + break; + } + + if(atSep) { + throw new IllegalArgumentException("Invalid object reference " + buf); + } + + return new EObjValue(objNames); + } + private static Expr maybeParseFuncCall(Token firstTok, TokBuf buf, Type exprType, boolean isSimpleExpr) { @@ -210,7 +270,7 @@ public class Expressionator } } - return new EFunc((String)firstTok.getValue(), params); + return new EFunc(firstTok.getValueStr(), params); } finally { if(!foundFunc) { @@ -254,7 +314,7 @@ public class Expressionator for(TokBuf paramBuf : params) { if(!paramBuf.hasNext()) { throw new IllegalArgumentException( - "Invalid empty parameter for function"); + "Invalid empty parameter for function " + paramBuf); } } } @@ -270,7 +330,7 @@ public class Expressionator } throw new IllegalArgumentException("Missing closing '" + FUNC_END_DELIM + - "' for function call"); + "' for function call " + buf); } private static boolean isSimpleExpression(TokBuf buf, Type exprType) { @@ -290,12 +350,11 @@ public class Expressionator } private static boolean isOp(Token t, String opStr) { - return ((t.getType() == TokenType.OP) && - opStr.equalsIgnoreCase((String)t.getValue())); + return ((t.getType() == TokenType.OP) && opStr.equalsIgnoreCase(t.getValueStr())); } private static WordType getWordType(Token t) { - return WORD_TYPES.get(((String)t.getValue()).toLowerCase()); + return WORD_TYPES.get(t.getValueStr().toLowerCase()); } private static void setWordType(WordType type, String... words) { @@ -307,21 +366,21 @@ public class Expressionator private static final class TokBuf { private final List _tokens; - private final boolean _topLevel; + private final TokBuf _parent; private int _pos; private Expr _pendingExpr; private TokBuf(List tokens) { - this(tokens, true); + this(tokens, null); } - private TokBuf(List tokens, boolean topLevel) { + private TokBuf(List tokens, TokBuf parent) { _tokens = tokens; - _topLevel = topLevel; + _parent = parent; } public boolean isTopLevel() { - return _topLevel; + return (_parent == null); } public int curPos() { @@ -352,12 +411,13 @@ public class Expressionator } public TokBuf subBuf(int start, int end) { - return new TokBuf(_tokens.subList(start, end), false); + return new TokBuf(_tokens.subList(start, end), this); } public void setPendingExpr(Expr expr) { if(_pendingExpr == null) { - throw new IllegalArgumentException("Found multiple expressions with no operator"); + throw new IllegalArgumentException( + "Found multiple expressions with no operator " + this); } _pendingExpr = expr; } @@ -371,6 +431,12 @@ public class Expressionator public boolean hasPendingExpr() { return (_pendingExpr != null); } + + @Override + public String toString() { + // FIXME show current pos + return null; + } } public static abstract class Expr @@ -415,17 +481,19 @@ public class Expressionator } } - private static final class EColumnValue extends Expr + private static final class EObjValue extends Expr { - private final String _colName; + private final List _objNames; - private EColumnValue(String colName) { - _colName = colName; + private EObjValue(List objNames) { + _objNames = objNames; } @Override public Object eval(RowContext ctx) { - return ctx.getRowValue(_colName); + // FIXME + return null; + // return ctx.getRowValue(_colName); } } -- 2.39.5