JavaScript中的语法/逻辑检查器?

3
我将为客户构建一个解决方案,允许他们创建非常基本的代码。我已经完成了一些基本语法验证,但卡在了变量验证上。
我知道JSLint使用Javascript来实现这一点,我想知道是否有好的方法来做到这一点。
例如,假设用户编写了以下代码:
moose = "barry"
base = 0
if(moose == "barry"){base += 100}

然后我试图找到一种方法来澄清“if”表达式是否符合正确的语法,变量moose是否已经初始化等等,但我不想逐个字符扫描来完成这个任务。代码是专门为这个应用程序构建的迷你语言,因此非常基础,不需要管理内存或其他任何东西。
我曾考虑过先按回车符拆分,然后再按空格拆分,但无法保证用户不会写类似于“moose =“barry””或“if(moose ==“barry”)”的内容,并且无法保证用户不会将条件结果保留在同一行内。
显然,编译器和解释器在更广泛的范围内执行此操作,但我不确定它们是否逐个字符执行此操作,如果确实如此,它们如何优化?
(另一个选择是将其发送回PHP进行处理,这将使浏览器免除责任)
有什么建议吗?
谢谢
在这种情况下,用例是有限的,语法永远不会扩展,在这种情况下,语言是一个简单的脚本语言,以便客户能够根据他们的用户输入创建独特的成本,最终结果将由PHP处理,以确保计算不能被最终用户调整并确保有一定的一致性。
例如,假设有1.00英镑的基础成本,并且表单上有一个名为“附加成本”的字段,语言将允许他们相对于“附加成本”字段操作基础成本。
base = 1;
if(additional > 100 && additional < 150){base += 50}
elseif(additional == 150){base *= 150}
else{base += additional;}

这是一个基本示例,展示了语言的使用方式。


感谢您提供的所有答案, 我已经调查了一个解析器,发现创建一个解析器比所需的要复杂得多。 在运行了几个测试并处理了数千行代码后,即使在单核P4和512mb内存的情况下,逐个字符地处理只需要几秒钟的时间(这远远少于客户使用的)。

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

仅花费了一个小时,我就编写了能够检查if语句的有效性并不会被嵌套的if、空格或奇怪的表达式所困惑的代码,剩下的工作很少,而一个解析器和完整的脚本语言则需要更长的时间。

你们给了我很多思考的东西,我已经评价了相关的答案,谢谢。


1
“这太过于笼统了。请详细描述这种“语言”是多么基础或复杂。” - meder omuraliev
基本数学运算(+,-,*,/), 基本条件语句(if,elseif,else) 变量仅存储整数、浮点数或字符串 没有循环 没有返回值 没有函数 没有类 正如我所说,这种语言的想法非常简单,它是基于在线构建器中创建的字段值来操作起始值的。 - TheBritishAreComing
你说只是基本的数学运算,但是你的例子中包含了变量赋值,这不仅仅是数学运算。此外,你的迷你语言还有if和else语句,相等运算符,高级的+=运算符。 - meder omuraliev
你可能需要编写一个小说明书,列出所有可能的语法组合和表达式组合。 - meder omuraliev
我在写作之前按了回车,请重新阅读一下,它将解释它将处理什么,尽管了解这些信息仍然是无关紧要的。问题与其他平台如何处理有关,或者是否有一种优化的方法来处理它,无论语言如何,该过程都会类似。 - TheBritishAreComing
3个回答

4
如果你真的想做到这一点,也就是说,如果你真的希望你的软件能够正常和可预测地工作,而不需要一堆奇怪的“不要这样做”的特殊情况,那么你需要为你的语言编写一个真正的解析器。一旦你有了它,你就可以将你语言中的任何程序转换成数据结构。通过这个数据结构,你将能够进行各种代码分析,包括至少曾经被称为使用定义和定义使用链分析的过程。
如果你设计了一种“编程语言”,使其能够在应用程序中进行一些脚本编写,那么无论你认为它多么微不足道,最终都会有人用它编写出一个惊人的大型程序。
我不知道是否有现成的解析器生成器可以生成JavaScript解析器。递归下降解析器并不难编写,但是它们可能难以维护,并且如果你没有很好的编写原始版本的经验,它们会使扩展语法变得有些困难。

谢谢你的回答。该语言是针对特定客户的应用程序而设计的,用于根据客户用户提供的信息计算成本。由于用例有限,它不会变得更加复杂,因为它不会影响软件的任何其他部分,只是为了让客户能够根据用户在构建的表单上做出的决策添加/编辑成本,使其尽可能简单和灵活。 - TheBritishAreComing
1
@James,你当然比我更了解你的应用程序,但是我回顾了自己长期以来对于自己的设计不可能变得更加复杂的理性化解释,而它们总是会变得更加复杂,尤其是那些实际上对人们有用的设计。 - Pointy
无论如何,如果这种语言有丝毫的趣味(从你的例子来看,它对我来说并不简单——任何具有表达式语法的东西都有各种各样有趣的复杂性),那么可靠地解释和分析它的唯一方法是使用真正的解析器。这就是为什么解析是计算机研究中一个有趣的领域:这是做这种事情的唯一方法。 - Pointy
第二段是精华。如果你设计了一种“编程语言”,使其能够在应用程序中进行一些脚本编写,那么无论你认为它有多么微不足道,最终总会有人用它编写出一个惊人的大型程序。 这是编程的真谛。 - jball

2
您可能需要查看JS/CC,这是一个生成JavaScript语言中的语法解析器的解析器生成器。您需要使用BNF和EBNF来描述您的语言。此外,JS/CC有其自己的语法(与实际的BNF/EBNF相似),用于指定语法。给定语法,JS/CC将为该语法生成解析器。
另一种选择是像Pointy所说的那样,从头开始编写自己的词法分析器和递归下降解析器。一旦有了BNF/EBNF,就不难了。我最近在JavaScript中从EBNF编写了一个解析器(语法非常简单,因此编写YMMV并不难)。
针对您关于“客户端特定”的评论,我也会分享我的经验。如果您提供脚本语言和脚本环境,则没有比实际解析器更好的路线。
通过一堆if-else来处理特殊情况将会非常痛苦且难以维护。大学一年级时,我尝试编写自己的语言。当时我还不知道任何关于递归下降解析器或者解析器的知识。我自己发现代码可以分解成标记。从那里开始,我使用了一堆if-else编写了一个非常笨重的解析器,并通过空格和其他字符将标记拆分(正是您所描述的)。最终结果非常糟糕。
一旦我了解了递归下降解析器,我为我的语言编写了一个语法,并轻松地在十分之一的时间内创建了一个解析器。如果您想避免很多痛苦,请编写一个实际的解析器。如果您按照当前路线进行,那么您将永远处理问题。您将不得不处理人们放置空格错误的情况,或者可能有太多或太少的空格。唯一的另一种选择是提供一个极其严格的结构(即,您必须在此语句后面恰好有 x 个空格),这可能会使您的脚本环境非常不吸引人。实际解析器将自动解决所有这些问题。

1

Javascript有一个名为'eval'的函数。

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

它将显示警报。您可以使用“eval”来执行基本代码。


根据jballs的评论,这完全没有回答问题。语言不是JavaScript,而是一种虚构的语言。我需要告诉用户他们在编写代码时犯了什么错误以及出错的位置。 - TheBritishAreComing
抱歉!我没有获取到你的问题关键字。这是我的错。 - erinus
绝对不要使用eval - eval是邪恶的 - 请参见http://blogs.msdn.com/b/ericlippert/archive/2003/11/01/53329.aspx。我质疑是否需要这样的功能。 - mozillanerd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接