包含逻辑运算符的表达式检验

1,205 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

最近项目有一个表达式校验的需求,特意记录下来学习探讨,以下是简化后的小案例,只进行了简单实现,如果有问题,欢迎大家指正!

功能简介

(1)该案例包括条件列表、逻辑运算符(并且、或者、非)、小括号、表达式输入框、校验按钮。

(2)条件列表展示需要进行运算的条件信息,点击一行,向表达式中指定光标后添加条件编号;点击逻辑运算符按钮,向表达式中指定光标后添加该逻辑运算符;点击校验按钮,校验表达式是否合法,并给出提示。

演示结果

整体效果

截屏2022-04-22 下午3.54.10.png

校验结果

截屏2022-04-22 下午3.56.46.png

截屏2022-04-22 下午3.57.41.png

截屏2022-04-22 下午3.58.46.png

还有很多种情况的提示,就不一一列举啦

思考

1、括号是否匹配,是否存在空括号;

2、逻辑运算符的使用是否合法,这个情况比较多,比如并且运算符需要连接两个条件、运算符不能连续、非运算符前需要有条件等,把所有不合法的情况列举出来,并给出相应的提示。

代码实现

校验模块

    checkExpression(string) {
      let msg = "校验通过";
      // 剔除空白符
      string = string.replace(/\s/g, "");

      // 错误情况,空字符串
      if (string === "") {
        msg = "请输入条件表达式";
        return msg;
      }

      // 错误情况,括号不配对
      const stack = [];
      for (let i = 0, item; i < string.length; i++) {
        item = string.charAt(i);
        if ("(" === item) {
          stack.push("(");
        } else if (")" === item) {
          if (stack.length > 0) {
            stack.pop();
          } else {
            stack.push(")");
          }
        }
      }
      if (stack.length !== 0) {
        msg = "括号不匹配";
        return msg;
      }

      // 空括号
      if (/\(\)/.test(string)) {
        msg = "存在空括号";
        return msg;
      }

      //错误情况,并且,或者不能在首位,且不能存在 \( (并且|或者) (并且|或者)\)
      const matchResult = string.match(/^(并且|或者)|(\((并且|或者))|((并且|或者)\))/g);
      if (matchResult) {
        msg =
          "条件运算符【" +
          (matchResult[0].includes("并且") ? "并且" : "或者") +
          "】只能用来连接两个完整的条件";
        return msg;
      }

      // 错误情况,运算符连续
      if (/(并且|或者){2,}/.test(string)) {
        msg = "运算符连续";
        return msg;
      }

      // 错误情况,非运算符前不能跟 ) 和条件
       if (/[\\)]非/.test(string)) {
        msg = "非运算符前需要有条件运算符";
        return msg;
      }

      // 错误情况,非运算符后不能跟 ) 并且, 或者
      if (new RegExp("非(\\)|并且|或者)").test(string)) {
        msg = "非运算符后需要紧跟条件";
        return msg;
      }

      // 错误情况,不能以运算符结尾
      if (/(并且|或者|非)$/.test(string)) {
        msg = "条件表达式不完整";
        return msg;
      }

      // 错误情况,(后面是运算符
      if (/\(["并且","或者"]/.test(string)) {
        return msg;
      }

      // 错误情况,)前面是运算符
      if (/["并且","或者"]\)/.test(string)) {
        return msg;
      }

      return msg;
    },

向当前光标位置后添加字符串

insertNode(str) {
      const tc = document.getElementById("expression-input");
      const tclen = tc.value.length;
      tc.focus();
      let startlength = 0;
      if (tc.selectionStart || tc.selectionStart == "0") {
        //IE11
        //火狐和谷歌
        startlength = tc.selectionStart + str.length;
        tc.value =
          tc.value.substr(0, tc.selectionStart) + str + tc.value.substring(tc.selectionEnd, tclen);
        this.operationExpression = tc.value;
        //设置光标位置,火狐和谷歌
        tc.selectionStart = startlength;
        tc.selectionEnd = startlength;
      } else {
        tc.value += str;
        this.operationExpression = tc.value;
        tc.focus();
      }
    }

总结

1、该功能主要是使用正则来实现的,正则的使用确实方便了很多功能的实现,通过这个小案例也算是对正则的复习。

2、考虑不合法情况的,对于提升思考问题的能力还是很有帮助的,我的能力一般,再接再厉吧。

3、向当前光标位置后添加字符串功能并不完善,有待优化。