use*_*336 7 javascript parsing recursive-descent abstract-syntax-tree
给定一个字符串:
var str1 = "25*5+5*7";
Run Code Online (Sandbox Code Playgroud)
如果不使用evalJavaScript中的构造函数,我怎样才能编写一个名为"output"的函数,该函数接收字符串并输出字符串的算术值,在本例中为160?
Ira*_*ter 11
这是一个完整的优先级表达式求值程序,遵循我在OP问题的注释中链接的递归解析思想.
为此,首先我为我想要处理的表达式编写了一个简单的BNF语法:
sum = product | sum "+" product | sum "-" product ;
product = term | product "*" term | product "/" term ;
term = "-" term | "(" sum ")" | number ;
Run Code Online (Sandbox Code Playgroud)
这本身需要一些简单而直接的经验.如果您没有使用BNF的经验,您会发现它非常适用于描述复杂的项目流,如表达式,消息,编程语言,......
使用该语法,我按照其他消息中概述的过程生成以下代码.显而易见的是,它是以一种愚蠢的机械方式由语法驱动的,因此如果你有这种语法就很容易写.
(未经测试.我不是一个JavaScript编码器.这肯定会包含一些语法/语义问题.我花了大约15分钟来编写代码.)
var SE="Syntax Error";
function parse(str) { // returns integer expression result or SE
var text=str;
var scan=1;
return parse_sum();
function parse_sum() {
var number, number2;
if (number=parse_product()==SE) return SE;
while (true) {
skip_blanks();
if (match("+") {
number2=parse_product();
if (number2==SE) return SE;
number+=number2;
}
else if (match('-')) {
{ number2=parse_product();
if (number2==SE) return SE;
number-=number2;
}
else return number;
}
}
function parse_product() {
var number, number2;
if (number=parse_number()==SE) return SE;
while (true) {
if (match("*") {
number2=parse_term();
if (number2==SE) return SE;
number*=number2;
}
else if (match('/')) {
number2=parse_term();
if (number2==SE) return SE;
number/=number2;
}
else return number;
}
}
function parse_term() {
var number;
skip_blanks();
if (match("(")) {
number=parse_sum();
if (number=SE) return SE;
skip_blanks();
if (!match(")") return SE;
}
else if match("-") {
number= - parse_term();
}
else if (number=parse_number()==SE) return SE;
return number;
}
function skip_blanks() {
while (match(" ")) { };
return;
}
function parse_number() {
number=0;
if (is_digit()) {
while (is_digit()) {}
return number;
}
else return SE;
}
var number;
function is_digit() { // following 2 lines are likely wrong in detail but not intent
if (text[scan]>="0" && text[scan]<="9") {
number=number*10+text[scan].toInt();
return true;
}
else return false;
}
function match(c) {
if (text[scan]==c)
{ scan++; return true }
else return false;
}
}
Run Code Online (Sandbox Code Playgroud)
编写这样的解析器/评估器是很简单的.请参阅我的答案,了解如何构建解析器(链接到如何构建求值程序).
您可以创建一个新脚本:
function parse(str) {
var s = document.createElement('script');
s.text = "window.result = " + str;
document.body.appendChild(s); // Run script
document.body.removeChild(s); // Clean up
return result; // Return the result
}
document.body.innerHTML = parse("5*5+5*5");Run Code Online (Sandbox Code Playgroud)
或者使用事件处理程序内容属性:
function parse(str) {
var el = document.createElement('div');
el.setAttribute('onclick', "this.result = " + str);
el.onclick(); // Run script
return el.result; // Return the result
}
document.body.innerHTML = parse("5*5+5*5");Run Code Online (Sandbox Code Playgroud)
请注意,这些方法是不安全的,而且同样邪恶,eval甚至更丑陋。所以我不推荐他们。