gpt4 book ai didi

javascript - 将 Java 标记化正则表达式转换为 Javascript

转载 作者:行者123 更新时间:2023-11-30 08:45:52 28 4
gpt4 key购买 nike

作为对我问题的回答Tokenizing an infix string in Java , 我得到了正则表达式 (?<=[^\.a-zA-Z\d])|(?=[^\.a-zA-Z\d] .但是,现在我正在用 Javascript 编写相同的代码,但我不知道如何让 Javascript 正则表达式来做同样的事情。

例如,如果我有字符串 sin(4+3)*2 ,我需要将其解析为 ["sin","(","4","+","3",")","*","2"]

我将使用什么正则表达式将字符串标记为每个单独的部分。

之前,我所做的只是对每个可能的标记进行字符串替换,并在其周围放置一个空格,然后在该空格处拆分。然而,该代码很快变得非常臃肿。

我需要拆分的运算符是标准数学运算符( +,-,*,/,^) ,以及函数名称 (sin,cos,tan,abs,etc...) 和逗号

什么是快速、高效的方法?

最佳答案

您可以利用正则表达式分组来执行此操作。您需要一个组合不同可能标记的正则表达式,并重复应用它。

我喜欢把不同的部分分开;它使维护和扩展更容易:

var tokens = [
"sin",
"cos",
"tan",
"\\(",
"\\)",
"\\+",
"-",
"\\*",
"/",
"\\d+(?:\\.\\d*)?"
];

您将所有这些粘合在一起,形成一个大的正则表达式,每个标记之间使用 |:

var rtok = new RegExp( "\\s*(?:(" + tokens.join(")|(") + "))\\s*", "g" );

然后您可以在源字符串上使用正则表达式操作进行分词:

function tokenize( expression ) {
var toks = [], p;

rtok.lastIndex = p = 0; // reset the regex
while (rtok.lastIndex < expression.length) {
var match = rtok.exec(expression);

// Make sure we found a token, and that we found
// one without skipping garbage

if (!match || rtok.lastIndex - match[0].length !== p)
throw "Oops - syntax error";

// Figure out which token we matched by finding the non-null group
for (var i = 1; i < match.length; ++i) {
if (match[i]) {
toks.push({
type: i,
txt: match[i]
});
// remember the new position in the string
p = rtok.lastIndex;
break;
}
}
}
return toks;
}

这只是将标记正则表达式与字符串重复匹配。正则表达式是用“g”标志创建的,因此正则表达式机制将在我们进行每次匹配后自动跟踪从何处开始匹配。当它没有看到匹配时,或者当它看到但必须跳过无效的内容才能找到它时,我们就知道存在语法错误。当它确实匹配时,它会在 token 数组中记录它匹配的 token (非空组的索引)和匹配的文本。通过记住匹配的标记索引,它可以让您省去标记化后必须弄清楚每个标记字符串 含义 的麻烦;你只需要做一个简单的数字比较。

因此调用 tokenize( "sin(4+3) * cos(25/3)") 返回:

[ { type: 1, txt: 'sin' },
{ type: 4, txt: '(' },
{ type: 10, txt: '4' },
{ type: 6, txt: '+' },
{ type: 10, txt: '3' },
{ type: 5, txt: ')' },
{ type: 8, txt: '*' },
{ type: 2, txt: 'cos' },
{ type: 4, txt: '(' },
{ type: 10, txt: '25' },
{ type: 9, txt: '/' },
{ type: 10, txt: '3' },
{ type: 5, txt: ')' } ]

token 类型 1 是 sin 函数,类型 4 是左括号,类型 10 是数字等。

编辑 — 如果您想要匹配像“x”和“y”这样的标识符,那么我可能会使用一组不同的标记模式,其中一个只是匹配任何标识符。这意味着解析器不会直接从词法分析器中找到关于“sin”和“cos”等的信息,但这没关系。这是 token 模式的替代列表:

var tokens = [
"[A-Za-z_][A-Za-z_\d]*",
"\\(",
"\\)",
"\\+",
"-",
"\\*",
"/",
"\\d+(?:\\.\\d*)?"
];

现在任何标识符都将是类型 1 token 。

关于javascript - 将 Java 标记化正则表达式转换为 Javascript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22118362/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com