翻译方法调用

  解析方法调用的语法,支持常量(双引号包含)、变量、函数(嵌套调用)作为入参。

  自动机:

  java实现:

 // 方法执行
    public String excuteMethod(String expression, JSONObject formData) throws Exception {
        if (null == expression) return "";
        while (expression.contains(" ")) expression = expression.replace(" ", "");
        Token token = this.excuteMethod(expression, 0, formData);
        if (null == token) throw new RuntimeException("error expression");
        return token.val;
    }

    // 方法执行,表达式不要有空格
    public Token excuteMethod(String expression, int left, JSONObject formData) throws Exception {
        String methodName = "";
        Stack<Token> paramStack = new Stack<Token>();
        STATE state = STATE.START;
        int len = expression.length(), right = left;
        while (right < len) {
            char c = expression.charAt(right);
            if (c == ')') {
                if (state == STATE.PARAM) {
                    // TODO 调用方法
                    String currentRes = this.methodSplit(methodName, paramStack);
                    Token token = new Token(currentRes, left, right);
                    return token;
                } else throw new RuntimeException(") error at " + right);
            }

            if (c == ',') {
                if (state == STATE.PARAM) {
                    right++;
                    state = STATE.WAIT_PARAM;
                } else throw new RuntimeException(", error at " + right);
                continue;
            }

            if (c == '(') {
                if (state == STATE.METHED_START) {
                    right++;
                    state = STATE.WAIT_PARAM;
                } else if (state == STATE.PARAM) {
                    // 递归调用
                    Token methodNameToken = paramStack.pop();
                    Token currentResToken = this.excuteMethod(expression, methodNameToken.getLeft(), formData);
                    if (null == currentResToken) throw new RuntimeException("error at " + right);
                    paramStack.push(currentResToken);
                    right = currentResToken.right + 1;
                    state = STATE.PARAM;
                } else {
                    System.out.println(state);
                    throw new RuntimeException("( error at " + right);
                }
                continue;
            }

            Token token = this.getToken(expression, right, formData);
            right = token.right + 1;
            if (state == STATE.START) {
                state = STATE.METHED_START;
                methodName = token.getVal();
            } else if (state == STATE.WAIT_PARAM) {
                // 常量、变量判断,变量取值
                String fieldVal = this.transField(token.getVal(), formData);
                token.setVal(fieldVal);
                paramStack.push(token);
                state = STATE.PARAM;
            } else throw new RuntimeException("token error at " + right);
        }
        return null;
    }

    private Token getToken(String expression, int left, JSONObject formData) {
        int len = expression.length(), right = left;
        if (right >= len) throw new RuntimeException("right:" + right + " out of len:" + len);
        StringBuilder builder = new StringBuilder();
        while (right < len) {
            char c = expression.charAt(right);
            if (c == '(' || c == ')' || c == ',') {
                // 不是转义符号的话,就是关键字符号,终止取值
                if (right <= 0 || expression.charAt(right - 1) != '/') {
                    right--;
                    break;
                }
            }
            builder.append(c);
            right++;
        }
        String val = builder.toString();
        return new Token(val, left, right);
    }

    public String transField(String val, JSONObject formData) {
        String reVal = "";
        if (val.charAt(0) == '"' && val.charAt(val.length() - 1) == '"') {
            // 常量
            reVal = val.substring(1, val.length() - 1);
        } else {
            // 表单数据
            String[] array = val.split("\\.");
            if ("baseInfo".equals(array[0])) reVal = formData.getJSONObject("baseInfo").getString(array[1]);
            else reVal = formData.getString(array[0]);
            System.out.println("field " + val + "::" + reVal);
        }
        return reVal;
    }

    @Data
    class Token {
        String val;
        int left, right;

        Token(String val, int left, int right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

    enum STATE {
        START,
        METHED_START,
        WAIT_PARAM,
        PARAM,
        METHED_END;
    }

 

posted @ 2023-04-26 14:32  牛有肉  阅读(20)  评论(0编辑  收藏  举报