首页 > 其他分享 >解析方法调用

解析方法调用

时间:2023-04-26 14:46:38浏览次数:54  
标签:调用 方法 STATE state right token new 解析 expression

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

  自动机:

  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;
    }

 

标签:调用,方法,STATE,state,right,token,new,解析,expression
From: https://www.cnblogs.com/niuyourou/p/17356003.html

相关文章

  • 13种权重的计算方法
    权重计算方法有很多种,不同的方法有不同的特点和适用情况。AHP层次分析法和熵值法在权重计算中属于比较常用的方法。除此之外,还有一些与权重计算相关的方法,今天一文总结了13种与权重计算相关的方法,大家可以对比选择使用。一、13种权重计算方法一句话简单描述13种权重计算方法,见......
  • SpringSecurity从入门到精通:其他权限校验方法&自定义权限校验方法
    其他权限校验方法我们前面都是使用@PreAuthorize注解,然后在在其中使用的是hasAuthority方法进行校验。SpringSecurity还为我们提供了其它方法例如:hasAnyAuthority,hasRole,hasAnyRole等。​这里我们先不急着去介绍这些方法,我们先去理解hasAuthority的原理,然后再去学......
  • 深度学习--LSTM网络、使用方法、实战情感分类问题
    深度学习--LSTM网络、使用方法、实战情感分类问题1.LSTM基础长短期记忆网络(LongShort-TermMemory,简称LSTM),是RNN的一种,为了解决RNN存在长期依赖问题而设计出来的。LSTM的基本结构:2.LSTM的具体说明LSTM与RNN的结构相比,在参数更新的过程中,增加了三个门,由左到右分别是遗忘门(也......
  • 用java调用oracle存储过程总结
    用java调用oracle存储过程总结[code]1、什么是存储过程。存储过程是数据库服务器端的一段程序,它有两种类型。一种类似于SELECT查询,用于检索数据,检索到的数据能够以数据集的形式返回给客户。另一种类似于INSERT或DELETE查询,它不返回数据,只是执行一个动作。......
  • Python pandas 保存Excel自动调整列宽的方法及示例代码
    方法1.  用pd.ExcelWriter和  worksheet.set_column 需要安装xlsxwriter方法2:使用StyleFrame自动调整fromstyleframeimportStyleFrameimportpandasaspdcolumns=['aaaaaaaaaaa','bbbbbbbbb','ccccccccccc',]df=pd.DataFrame(data={......
  • vue-cli使用方法
    是什么?vue-clivuecommandlineinterface是vue命令行接口工具怎么用?1.安装npm:【Win7】只支持node.jsv13.14.0或更早1)到官网下载https://nodejs.org/download/release/v13.14.0/node-v13.14.0-x64.msi2)注意在安装node.js时,勾选“Automaticallyinstalltheneces......
  • Linux基本安装方法
    centos6.4 这里为大家介绍Linux的安装,安装步骤比较繁琐,现在其实云服务器挺普遍的,价格也便宜,如果自己不想搭建,也可以直接买一台学习用用,参考各大云服务器比较。本次以centos6.4为例。 centos下载地址:可以去官网下载最新版本:https://www.centos.org/download/ 以......
  • 局域网实现文件上传下载功能实例解析
    ​IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头。 一. 两个必要响应头Accept-Ranges、ETag        客户端每次提交下载请求时,服务端都要添加这两个响应头,以保证客户端和服务端将此下载识别为可以断点续传......
  • JEECG使用反向代理 积木报表无法正常使用的解决方法
    发现JEECG反向代理开启后  重设了Host头,导致积木框架的数据接口url拼接异常Nginx配置增加:#通过反向代理访问积木报表,Jeecg框架内的菜单配置需要写成绝对路径:http://localhost:3000/jeecg-boot/jmreport/list?token=${token}location^~/jeecg-boot/jmreport/{#p......
  • JavaScript方法获取屏幕缩放比例与分辨率
    我们在开发一些前端页面的时候,会考虑到一些设备屏幕的兼容性问题,这个时候需要根据屏幕的分辨率以及缩放比例来进行实时的宽高设定,所以我总结了用JavaScript方法进行获取用户电脑屏幕的分辨率和缩放比例的数据:  获取屏幕缩放比例//获取屏幕缩放比例functiongetRatio(){......