Search in sources :

Example 1 with NativeArrayNode

use of org.beetl.core.statement.nat.NativeArrayNode in project beetl2.0 by javamonkey.

the class AntlrProgramBuilder method parseNativeCallExpression.

protected NativeCallExpression parseNativeCallExpression(NativeCallContext ncc) {
    NativeCallExpression nativeExp = null;
    List<ParseTree> list = ncc.children;
    // nativeCall: nativeVarRefChain (nativeMethod|nativeArray| PERIOD nativeVarRefChain)*;
    NativeVarRefChainContext first = (NativeVarRefChainContext) list.get(0);
    List<TerminalNode> ids = first.Identifier();
    StringBuilder clsSb = new StringBuilder();
    // 是类静态调用还是实例调用
    boolean isCls = false;
    int i = 0;
    for (; i < ids.size(); i++) {
        String text = ids.get(i).getText();
        char c = text.charAt(0);
        if (c >= 'A' && c <= 'Z') {
            clsSb.append(text);
            isCls = true;
            break;
        } else {
            clsSb.append(text).append(".");
        }
    }
    ClassNode clsNode = null;
    InstanceNode insNode = null;
    if (isCls) {
        clsNode = new ClassNode(clsSb.toString());
        // 指向下一个属性或者静态方法
        i++;
    } else {
        // 变量的属性引用,回到第一个,构造一个变量
        String varName = ids.get(0).getText();
        VarRef ref = new VarRef(new VarAttribute[0], false, null, this.getBTToken(varName, ncc.start.getLine()));
        this.pbCtx.setVarPosition(varName, ref);
        insNode = new InstanceNode(ref);
        i = 1;
    }
    List<NativeNode> nativeList = new ArrayList<NativeNode>();
    for (int j = i; j < ids.size(); j++) {
        // 剩下的是属性
        NativeAtrributeNode attribute = new NativeAtrributeNode(ids.get(j).getText());
        nativeList.add(attribute);
    }
    for (int z = 1; z < list.size(); z++) {
        ParseTree tree = list.get(z);
        if (tree instanceof NativeMethodContext) {
            NativeMethodContext methodCtx = (NativeMethodContext) tree;
            NativeMethodNode methodNode = null;
            String method = null;
            NativeNode lastNode = nativeList.get(nativeList.size() - 1);
            if (lastNode instanceof NativeAtrributeNode) {
                method = ((NativeAtrributeNode) lastNode).attribute;
                // 
                nativeList.remove(nativeList.size() - 1);
            } else {
                String msg = null;
                if (lastNode instanceof NativeArrayNode) {
                    msg = "[]()";
                } else {
                    msg = "()()";
                }
                BeetlException ex = new BeetlException(BeetlException.PARSER_NATIVE_ERROR, msg);
                ex.pushToken(this.getBTToken(methodCtx.getStart()));
                throw ex;
            }
            // 解析参数
            List<ExpressionContext> expCtxList = methodCtx.expression();
            Expression[] exp = this.parseExpressionCtxList(expCtxList);
            methodNode = new NativeMethodNode(method, exp);
            nativeList.add(methodNode);
        } else if (tree instanceof NativeArrayContext) {
            ExpressionContext expCtx = ((NativeArrayContext) tree).expression();
            Expression exp = this.parseExpress(expCtx);
            NativeArrayNode arrayNode = new NativeArrayNode(exp);
            nativeList.add(arrayNode);
        } else if (tree instanceof NativeVarRefChainContext) {
            List<TerminalNode> nodes = ((NativeVarRefChainContext) tree).Identifier();
            for (TerminalNode node : nodes) {
                NativeAtrributeNode attributeNode = new NativeAtrributeNode(node.getText());
                nativeList.add(attributeNode);
            }
        } else {
            // 其他节点,这段语法写的不好,造成解析困难,但先这样了
            continue;
        }
    }
    NativeNode[] chain = nativeList.toArray(new NativeNode[0]);
    if (clsNode != null) {
        nativeExp = new NativeCallExpression(clsNode, chain, this.getBTToken(ncc.start));
    } else {
        nativeExp = new NativeCallExpression(insNode, chain, this.getBTToken(ncc.start));
    }
    return nativeExp;
}
Also used : VarRef(org.beetl.core.statement.VarRef) NativeArrayNode(org.beetl.core.statement.nat.NativeArrayNode) BeetlException(org.beetl.core.exception.BeetlException) InstanceNode(org.beetl.core.statement.nat.InstanceNode) ArrayList(java.util.ArrayList) NativeNode(org.beetl.core.statement.nat.NativeNode) NativeAtrributeNode(org.beetl.core.statement.nat.NativeAtrributeNode) ClassNode(org.beetl.core.statement.nat.ClassNode) NativeVarRefChainContext(org.beetl.core.parser.BeetlParser.NativeVarRefChainContext) NativeArrayContext(org.beetl.core.parser.BeetlParser.NativeArrayContext) NativeCallExpression(org.beetl.core.statement.NativeCallExpression) StatementExpressionContext(org.beetl.core.parser.BeetlParser.StatementExpressionContext) ExpressionContext(org.beetl.core.parser.BeetlParser.ExpressionContext) ParExpressionContext(org.beetl.core.parser.BeetlParser.ParExpressionContext) ContentBodyExpression(org.beetl.core.statement.ContentBodyExpression) ArthExpression(org.beetl.core.statement.ArthExpression) JsonMapExpression(org.beetl.core.statement.JsonMapExpression) CompareExpression(org.beetl.core.statement.CompareExpression) FunctionExpression(org.beetl.core.statement.FunctionExpression) IncDecExpression(org.beetl.core.statement.IncDecExpression) Expression(org.beetl.core.statement.Expression) AndExpression(org.beetl.core.statement.AndExpression) StatementExpression(org.beetl.core.statement.StatementExpression) NativeCallExpression(org.beetl.core.statement.NativeCallExpression) NegExpression(org.beetl.core.statement.NegExpression) FormatExpression(org.beetl.core.statement.FormatExpression) TernaryExpression(org.beetl.core.statement.TernaryExpression) OrExpression(org.beetl.core.statement.OrExpression) JsonArrayExpression(org.beetl.core.statement.JsonArrayExpression) NotBooleanExpression(org.beetl.core.statement.NotBooleanExpression) TerminalNode(org.antlr.v4.runtime.tree.TerminalNode) NativeMethodNode(org.beetl.core.statement.nat.NativeMethodNode) ParseTree(org.antlr.v4.runtime.tree.ParseTree) NativeMethodContext(org.beetl.core.parser.BeetlParser.NativeMethodContext)

Example 2 with NativeArrayNode

use of org.beetl.core.statement.nat.NativeArrayNode in project beetl2.0 by javamonkey.

the class NativeCallExpression method infer.

@Override
public void infer(InferContext inferCtx) {
    Type type = null;
    if (insNode != null) {
        insNode.ref.infer(inferCtx);
        type = insNode.ref.type.copy();
    } else {
        Class cls = inferCtx.gt.loadClassBySimpleName(this.clsNode.cls);
        if (cls == null) {
            BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "该类不存在");
            be.pushToken(GrammarToken.createToken(clsNode.cls, token.line));
            throw be;
        }
        type = new Type(cls);
    }
    for (NativeNode node : chain) {
        if (type.cls == Object.class) {
            this.type = type;
            // 以后生成代码有问题
            return;
        }
        if (node instanceof NativeAtrributeNode) {
            String attr = ((NativeAtrributeNode) node).attribute;
            try {
                Field f = type.cls.getField(attr);
                Class c = f.getType();
                type.cls = c;
            } catch (SecurityException e) {
                BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "无法访问属性", e);
                be.pushToken(GrammarToken.createToken(attr, token.line));
                throw be;
            } catch (NoSuchFieldException e) {
                BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "无此属性", e);
                be.pushToken(GrammarToken.createToken(attr, token.line));
                throw be;
            }
        } else if (node instanceof NativeArrayNode) {
            if (!type.cls.isArray()) {
                BeetlException be = new BeetlException(BeetlException.ARRAY_TYPE_ERROR);
                // 最好是把上一个字符显示出来
                be.pushToken(GrammarToken.createToken("[]", token.line));
                throw be;
            }
            type.cls = type.cls.getComponentType();
        } else if (node instanceof NativeMethodNode) {
            NativeMethodNode methodNode = (NativeMethodNode) node;
            String method = methodNode.method;
            Expression[] expList = methodNode.paras;
            Class[] argTypes = expList.length == 0 ? ObjectUtil.EMPTY_CLASS_ARRAY : new Class[expList.length];
            for (int i = 0; i < expList.length; i++) {
                expList[i].infer(inferCtx);
                argTypes[i] = expList[i].type.cls;
            }
            try {
                ObjectMethodMatchConf conf = ObjectUtil.findMethod(type.cls, method, argTypes);
                if (conf == null) {
                    type.cls = Object.class;
                } else {
                    type.cls = conf.method.getReturnType();
                }
            } catch (SecurityException e) {
                BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "不能调用方法");
                be.pushToken(GrammarToken.createToken(method, token.line));
                throw be;
            }
        }
    }
    this.type = type;
}
Also used : NativeArrayNode(org.beetl.core.statement.nat.NativeArrayNode) BeetlException(org.beetl.core.exception.BeetlException) NativeNode(org.beetl.core.statement.nat.NativeNode) NativeAtrributeNode(org.beetl.core.statement.nat.NativeAtrributeNode) Field(java.lang.reflect.Field) ObjectMethodMatchConf(org.beetl.core.om.ObjectMethodMatchConf) NativeMethodNode(org.beetl.core.statement.nat.NativeMethodNode)

Example 3 with NativeArrayNode

use of org.beetl.core.statement.nat.NativeArrayNode in project beetl2.0 by javamonkey.

the class NativeCallExpression method evaluate.

public Object evaluate(Context ctx) {
    Class targetCls = null;
    Object targetObj = null;
    NativeNode lastNode = null;
    if (insNode != null) {
        targetObj = insNode.ref.evaluate(ctx);
        if (targetObj != null) {
            targetCls = targetObj.getClass();
        }
        lastNode = insNode;
    } else {
        targetCls = ctx.gt.loadClassBySimpleName(this.clsNode.cls);
        if (targetCls == null) {
            BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "该类不存在");
            be.pushToken(GrammarToken.createToken(clsNode.cls, token.line));
            throw be;
        }
        lastNode = clsNode;
    }
    for (NativeNode node : chain) {
        if (node instanceof NativeAtrributeNode) {
            String attr = ((NativeAtrributeNode) node).attribute;
            try {
                checkNull(targetCls, lastNode);
                Field f = targetCls.getField(attr);
                if (!Modifier.isStatic(f.getModifiers())) {
                    checkNull(targetObj, lastNode);
                }
                targetObj = f.get(targetObj);
                targetCls = f.getType();
            } catch (SecurityException e) {
                BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "不能调用属性", e);
                be.pushToken(GrammarToken.createToken(attr, token.line));
                throw be;
            } catch (NoSuchFieldException e) {
                BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "无此属性", e);
                be.pushToken(GrammarToken.createToken(attr, token.line));
                throw be;
            } catch (IllegalArgumentException e) {
                BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "访问属性出错", e);
                be.pushToken(GrammarToken.createToken(attr, token.line));
                throw be;
            } catch (IllegalAccessException e) {
                BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "访问属性出错", e);
                be.pushToken(GrammarToken.createToken(attr, token.line));
                throw be;
            }
        } else if (node instanceof NativeArrayNode) {
            checkNull(targetCls, lastNode);
            if (!targetCls.isArray()) {
                BeetlException be = new BeetlException(BeetlException.ARRAY_TYPE_ERROR);
                // 最好是把上一个字符显示出来
                be.pushToken(GrammarToken.createToken("[]", token.line));
                throw be;
            }
            Expression exp = ((NativeArrayNode) node).exp;
            Object value = exp.evaluate(ctx);
            if (value instanceof Number) {
                int index = ((Number) value).intValue();
                targetObj = ((Object[]) targetObj)[index];
                if (targetObj != null) {
                    targetCls = targetObj.getClass();
                } else {
                    // todo or component of array
                    targetCls = null;
                }
            } else {
                BeetlException be = new BeetlException(BeetlException.ARRAY_INDEX_ERROR, "数组指针必须是Number类型");
                be.pushToken(GrammarToken.createToken("[]", token.line));
                throw be;
            }
        } else if (node instanceof NativeMethodNode) {
            NativeMethodNode methodNode = (NativeMethodNode) node;
            String method = methodNode.method;
            Expression[] expList = methodNode.paras;
            this.checkPermit(ctx, targetCls, targetObj, method);
            Object[] args = expList.length == 0 ? ObjectUtil.EMPTY_OBJECT_ARRAY : new Object[expList.length];
            Class[] parameterType = new Class[args.length];
            for (int i = 0; i < expList.length; i++) {
                args[i] = expList[i].evaluate(ctx);
                parameterType[i] = args[i] == null ? null : args[i].getClass();
            }
            this.checkNull(targetCls, lastNode);
            ObjectMethodMatchConf mf = ObjectUtil.findMethod(targetCls, method, parameterType);
            if (mf == null) {
                BeetlException ex = new BeetlException(BeetlParserException.NATIVE_CALL_INVALID, "根据参数未找到匹配的方法" + method + BeetlUtil.getParameterDescription(parameterType));
                ex.pushToken(GrammarToken.createToken(lastNode.getName(), token.line));
                throw ex;
            }
            if (targetObj == null && !Modifier.isStatic(mf.method.getModifiers())) {
                BeetlException ex = new BeetlException(BeetlException.NULL);
                ex.pushToken(GrammarToken.createToken(lastNode.getName(), token.line));
                throw ex;
            }
            try {
                targetObj = ObjectUtil.invoke(targetObj, mf, args);
                if (targetObj != null) {
                    targetCls = targetObj.getClass();
                } else {
                    targetCls = null;
                }
            } catch (SecurityException e) {
                BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "不能调用方法", e);
                be.pushToken(GrammarToken.createToken(method, token.line));
                throw be;
            } catch (IllegalArgumentException e) {
                BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "错误的参数", e);
                be.pushToken(GrammarToken.createToken(method, token.line));
                throw be;
            } catch (IllegalAccessException e) {
                BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "无法访问方法", e);
                be.pushToken(GrammarToken.createToken(method, token.line));
                throw be;
            } catch (InvocationTargetException e) {
                BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "内部调用报错", e.getTargetException());
                be.pushToken(GrammarToken.createToken(method, token.line));
                throw be;
            }
        }
        lastNode = node;
    }
    return targetObj;
}
Also used : NativeArrayNode(org.beetl.core.statement.nat.NativeArrayNode) BeetlException(org.beetl.core.exception.BeetlException) NativeNode(org.beetl.core.statement.nat.NativeNode) InvocationTargetException(java.lang.reflect.InvocationTargetException) NativeAtrributeNode(org.beetl.core.statement.nat.NativeAtrributeNode) Field(java.lang.reflect.Field) ObjectMethodMatchConf(org.beetl.core.om.ObjectMethodMatchConf) NativeMethodNode(org.beetl.core.statement.nat.NativeMethodNode)

Aggregations

BeetlException (org.beetl.core.exception.BeetlException)3 NativeArrayNode (org.beetl.core.statement.nat.NativeArrayNode)3 NativeAtrributeNode (org.beetl.core.statement.nat.NativeAtrributeNode)3 NativeMethodNode (org.beetl.core.statement.nat.NativeMethodNode)3 NativeNode (org.beetl.core.statement.nat.NativeNode)3 Field (java.lang.reflect.Field)2 ObjectMethodMatchConf (org.beetl.core.om.ObjectMethodMatchConf)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 ArrayList (java.util.ArrayList)1 ParseTree (org.antlr.v4.runtime.tree.ParseTree)1 TerminalNode (org.antlr.v4.runtime.tree.TerminalNode)1 ExpressionContext (org.beetl.core.parser.BeetlParser.ExpressionContext)1 NativeArrayContext (org.beetl.core.parser.BeetlParser.NativeArrayContext)1 NativeMethodContext (org.beetl.core.parser.BeetlParser.NativeMethodContext)1 NativeVarRefChainContext (org.beetl.core.parser.BeetlParser.NativeVarRefChainContext)1 ParExpressionContext (org.beetl.core.parser.BeetlParser.ParExpressionContext)1 StatementExpressionContext (org.beetl.core.parser.BeetlParser.StatementExpressionContext)1 AndExpression (org.beetl.core.statement.AndExpression)1 ArthExpression (org.beetl.core.statement.ArthExpression)1 CompareExpression (org.beetl.core.statement.CompareExpression)1