javascript - 如何分析无限嵌套的公式?
问题描述
我有一个只有匹配元素的公式\w{3,4}
。有四个运算符:+
, +-
, /
(总是括在括号中)v
和普通括号:(
and )
。
整个公式总是用括号括起来。我只需要能够嵌套到 4 的深度,但如果可能的话,最好是无限深度。
以下是应匹配的有效公式的几个示例(xxxx 为\w{3,4}
):
- (xxxx)
- (xxxx/xxxx/xxxx)
- (xxxx+xxxx)
- (xxxx+-xxxx)
- ((xxxx/xxxx)+xxxx)
- (((xxxx/xxxx)+-xxxx)v(xxxx))
- ((xxxx/xxxx)+-(xxxx/xxxx)+xxxx)
- ((xxxx/xxxx)+-(((xxxx/xxxx)+-xxxx)/xxxx)+xxxx)
- (((((xxxx/xxxx)+-((xxxx/xxxx/xxxx)+-xxxx)/xxxx)+xxxx)v((xxxx/(xxxx/xxxx))+xxxx))
正如你所看到的,基本上每个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)));
}
它可以用来分析公式而不是正则表达式吗?
解决方案
您可以从字符串中匹配并删除带有运算符的操作数,然后删除配对的()
子字符串,直到没有匹配项,然后检查字符串是否为空。如果为空,则字符串有效,否则无效。
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
块中完成的:如果它们相同,则不再进行替换,我们可以继续检查字符串是否为空。
推荐阅读
- altair - 在属于 Altair Cross-Filter Dashboard 的单个图表上滚动
- json - 使用 dart 创建发布请求,将信息作为 json 数据通过请求正文传递
- php - Polylang pll_e() 搞砸了文本定位 - 我的语法有什么问题?
- sql - Teradata 左连接删除空值
- asp.net - ListView SelectedItem Wpf上的DeleteButton绑定
- reactjs - useContext 在子组件中返回 null,而不是父组件?
- r - 使用 R CMD SHLIB 从 .c 文件生成数据
- python - ScrolledText 不会一直向下滚动文本框。特金特
- r - 如何从R中的混合字符串中提取数字
- sql-server - SQL Server 变更数据捕获 - 直接查询系统表