3

我正在为客户构建一个解决方案,允许他们创建非常基本的代码,现在我已经完成了一些基本的语法验证,但我被困在变量验证上。

我知道 JSLint 使用 Javascript 来做到这一点,我想知道是否有人知道这样做的好方法。

因此,例如说用户编写了代码

moose = "barry"
base = 0
if(moose == "barry"){base += 100}

然后我试图找到一种方法来澄清“if”表达式的语法是否正确,如果变量 moose 已被初始化等,但我想在不逐字符扫描的情况下执行此操作,代码是一种迷你语言专为这个应用程序构建,所以非常基础,不需要管理内存或类似的东西。

我曾考虑过先按回车然后按空格进行拆分,但没有什么可以说用户不会写类似moose="barry"or的东西if(moose=="barry") ,也没有什么可以说用户不会保持内联条件的结果。

显然,编译器和解释器在更广泛的范围内执行此操作,但我不确定他们是否逐个字符地执行此操作,以及他们是否进行了优化?

(另一种选择是我可以将其发送回 PHP 进行处理,然后让浏览器承担责任)

有什么建议么?

谢谢

用例有限,在这种情况下永远不会扩展语法,语言是一种简单的脚本语言,使客户端能够根据用户输入创建唯一的成本,最终结果将由 PHP 处理,以确保计算最终用户无法调整并确保有一定的一致性。

例如,假设基本成本为 1.00 英镑,并且表单上有一个名为“附加成本”的字段,该语言将允许他们相对于“附加成本”字段操纵基本成本。

所以

base = 1;
if(additional > 100 && additional < 150){base += 50}
elseif(additional == 150){base *= 150}
else{base += additional;}

这是如何使用该语言的一个基本示例。


感谢您的所有回答,我已经调查了一个解析器,创建一个解析器将比使用 1000 行代码运行多个测试所需的复杂得多,并且发现一个字符一个字符的处理即使在单核 P4 512mb 内存(远小于客户使用)

我决定构建一个基于 PHP 的语法检查器,它将检查信息并将变量等转换为有效的 PHP 代码,同时它正在检查它(以便稍后可以在不重新编译的情况下调用它)使用 this 而不是 javascript 这似乎更合适并且将允许出现更复杂的代码而不妨碍验证过程

只花了一个小时,我的代码能够检查 if 语句的有效性,并且不会被嵌套的 if、空格或奇数表达式混淆,几乎没有什么需要检查的,而解析器和成熟的脚本语言会花费更长的时间

你们都给了我很多思考,我已经对相关答案进行了评分,谢谢

4

3 回答 3

4

如果你真的想这样做——我的意思是,如果你真的希望你的软件能够正常工作且可预测,没有一堆奇怪的“不要这样做”的特殊情况——你将不得不编写一个真正的您的语言的解析器。一旦你有了它,你就可以将你语言中的任何程序转换为数据结构。使用该数据结构,您将能够对代码进行各种分析,包括至少曾经被称为使用定义和定义使用链分析的过程。

如果您编写了一种“编程语言”,可以在应用程序中编写一些脚本,那么无论您认为它多么微不足道,最终都会有人用它编写一个令人震惊的大程序。

我不知道有任何现成的解析器生成器可以生成 JavaScript 解析器。递归下降解析器编写起来并不难,但它们可能很难维护,并且使扩展语法有点困难(尤其是如果您对制作原始版本不是很有经验)。

于 2010-12-27T16:59:50.057 回答
2

您可能想查看JS/CC,它是一个解析器生成器,它在 Javascript 中为语法生成器生成解析器。您将需要弄清楚如何使用 BNF 和 EBNF 来描述您的语言。此外,JS/CC 有自己的语法(有点接近实际的 BNF/EBNF)来指定语法。给定语法,JS/CC 将为该语法生成​​一个解析器。

正如 Pointy 所说,您的另一个选择是从头开始编写自己的词法分析器和递归下降解析器。一旦你有了 BNF/EBNF,就没有那么难了。我最近用 Javascript 从 EBNF 编写了一个解析器(语法非常简单,所以编写一个 YMMV 并不难)。

解决您关于它是“客户特定”的评论。我也将在这里添加我自己的经验。如果您要提供脚本语言和脚本环境,那么没有比实际解析器更好的方法了。

通过一堆 if-else 处理特殊情况将非常痛苦,并且是维护的噩梦。当我还是大学一年级的时候,我试着写我自己的语言。这是在我对递归下降解析器或一般的解析器一无所知之前。我自己发现代码可以分解为令牌。从那里,我使用一堆 if-else 编写了一个极其笨拙的解析器,并且还用空格和其他字符(正是你所描述的)分割标记。最终的结果是可怕的。

一旦我阅读了递归下降解析器,我就为我的语言编写了一个语法,并且在我编写原始解析器所需的十分之一的时间内轻松地创建了一个解析器。说真的,如果您想省去很多痛苦,请编写一个实际的解析器。如果你沿着当前的路线走,你将永远解决问题。您将不得不处理人们将空间放在错误位置的情况,或者他们可能有一个太多(或一个太少)的空间。唯一的另一种选择是提供一个非常严格的结构(即,您必须在此语句后面有正好x 个空格),这可能会使您的脚本环境非常没有吸引力。一个实际的解析器会自动修复所有这些问题。

于 2010-12-27T18:10:58.723 回答
1

Javascript has a function 'eval'.

var code = 'alert(1);';
eval(code);

It will show alert. You can use 'eval' to execute basic code.

于 2010-12-27T16:42:26.133 回答