大家好,感谢阅读。
我正在尝试做一个类似 Google 的计算器。你输入一个字符串,它会确定是否可以计算并返回结果。
我从基础开始慢慢构建:+ - / *
和括号处理。
我希望随着时间的推移改进计算器,并且在一段时间前学习了一些词法分析的知识,我构建了一个令牌列表和相关的正则表达式模式。
这种工作在像 Lex 和 Yacc 这样的语言中很容易应用,但是我正在开发一个仅使用 Javascript 的应用程序。
我试图将想法转录到 Javascript 中,但我无法找出如何以清晰美观的方式处理所有内容,特别是嵌套的括号。
分析
让我们定义什么是计算器查询:
// NON TERMINAL EXPRESSIONS //
query -> statement
query -> ε // means end of query
statement -> statement operator statement
statement -> ( statement )
statement -> prefix statement
statement -> number
number -> integer
number -> float
// TERMINAL EXPRESSIONS //
operator -> [+*/%^-]
prefix -> -
integer -> [0-9]+
float -> [0-9]+[.,][0-9]+
Javascript
词法分析主要是验证是否存在不符合运算符、前缀、整数和浮点数终极表达式之一的内容。这可以简化为一个正则表达式:
(我添加了空格以使其更易读)
var calcPat =
/^ (\s*
( ([+/*%^-]) | ([0-9]+) | ([0-9]+[.,][0-9]+) | (\() | (\)) )
)+ \s* $/;
如果这个测试通过,查询就在词法上正确,需要进行语法检查以确定是否可以计算。这是棘手的部分。我不会粘贴代码,因为它不干净也不易理解,但我会解释我遵循的过程以及我卡住的原因:
我创建了一个名为 isStatement(string) 的方法,该方法应该递归调用自身。主要想法是将字符串拆分为“潜在”语句,然后检查它们是否真正是语句并组成一个整体。 过程如下:
- 如果前两个标记是数字后跟运算符: - 然后, -- 如果剩余的只有一个标记,并且它是一个数字: --- 那么这是一个语句。 --- 否则,请检查剩余的标记是否形成语句(递归调用)
-否则,如果第一个标记是括号 -然后,找到匹配的右括号并检查括号内是否为语句(递归) --还要检查右括号后是否有内容,并且如果与括号结构相关联,则是否构成语句。
问题是什么?
我的问题是当存在嵌套结构时,我无法找到匹配的括号。我该怎么做? 此外,正如您所看到的,这不是特别通用和清晰的语法检查算法。您有任何改进此模式的想法吗?
非常感谢您抽出时间阅读所有内容。 Gael
(PS:正如您可能已经注意到的,我不是以英语为母语的人!很抱歉有错别字!)