首页 > 解决方案 > 如何分析无限嵌套的公式?

问题描述

我有一个只有匹配元素的公式\w{3,4}。有四个运算符:+, +-, /(总是括在括号中)v和普通括号:(and )

整个公式总是用括号括起来。我只需要能够嵌套到 4 的深度,但如果可能的话,最好是无限深度。

以下是应匹配的有效公式的几个示例(xxxx 为\w{3,4}):

正如你所看到的,基本上每个xxxx都可以被一个完整的公式替换,它应该仍然有效。我不确定正则表达式是否适合去这里,所以我也愿意接受其他建议。

这是我的正则表达式,它适用于深度 2,但对我来说似乎过于复杂:

^(?:\(?(?:\w{3,4}|\(\w{3,4}(?:\/\w{3,4})+\))(?:\+-?(?:\w{3,4}|\(\w{3,4}(?:\/\w{3,4})+\)))*\)?$|\({2}(?:\w{3,4}|\(\w{3,4}(?:\/\w{3,4})+\))(?:\+-?(?:\w{3,4}|\(\w{3,4}(?:\/\w{3,4})+\)))*\)v\((?:\w{3,4}|\(\w{3,4}(?:\/\w{3,4})+\))(?:\+-?(?:\w{3,4}|\(\w{3,4}(?:\/\w{3,4})+\)))*\){2})$

试验场:https ://regex101.com/r/YGDENq/2


编辑:我还使用解析器来删除不必要的括号:

console.log(fixParenthesis('(((((xxxx/xxxx)+-(xxxx/xxxx)+xxxx))))'));

function fixParenthesis(string) {
    function parse(tokens, depth = 0) {
        let ast = [];

        while (tokens.length) {
            switch (tokens[0]) {
                case '(':
                    tokens.shift();
                    ast.push(parse(tokens, depth + 1));
                    break;
                case ')':
                    if (!depth)
                        throw new SyntaxError('mismatched )');
                    tokens.shift();
                    return ast;
                default:
                    ast.push(tokens.shift());
            }
        }

        if (depth) {
            throw new SyntaxError('mismatched (');
        }

        return ast;
    }

    function generate(el) {
        if (!Array.isArray(el))
            return el;

        while (el.length === 1 && Array.isArray(el[0]))
            el = el[0];

        return `(${el.map(generate).join('')})`;
    }

    return generate(parse(string.match(/\(|\)|[^()]+/g)));
}

它可以用来分析公式而不是正则表达式吗?

标签: javascriptregex

解决方案


您可以从字符串中匹配并删除带有运算符的操作数,然后删除配对的()子字符串,直到没有匹配项,然后检查字符串是否为空。如果为空,则字符串有效,否则无效。

var s = "((abcd/abc)+-(ab1/abd3)+dfg3)";
// Preliminary checks:
if (/^[()\w+\/-]*$/.test(s)) { // Only allowed chars?
 if (!/\bvv\b|(?!\+-)[+\/-]{2,}|[+\/-]+v\b|\bv[+\/-]+/.test(s)) { // No repeating delimiters?
  var prev=s;
  var res = s.replace(/\+-?|[-\/v]|\b\w{3,4}\b/g, '');
  while(res != prev) {
    prev = res;
    res = res.replace(/\(\)/g, '');  
  }
  if (res.length > 0) {
     document.body.innerHTML= "Not valid";
  } else {
     document.body.innerHTML = "Valid";
  }
 }
}

/\+-?|[-\/v]|\w{3,4}/g则表达式匹配

  • \+-?- 一个+-+
  • |- 或者
  • [-\/v]- -,/v
  • |- 或者
  • \w{3,4}- 三四个字的字符。

删除括号是在新字符串与前一个字符串进行比较.replace(/\(\)/g, '')while块中完成的:如果它们相同,则不再进行替换,我们可以继续检查字符串是否为空。


推荐阅读