scheme - Scheme Lisp - 对任意算术表达式使用 eval
问题描述
我正在尝试使用 eval 在方案中评估任意和嵌套的算术表达式。表达式由数字、运算符、常量绑定和括号组成。例如,(eval (+ 1 1))
或(eval (+ (* 1 2) 3))
问题是,表达式也可能有不平衡的括号,比如
(eval ((+ 1 1))
,scheme 中的读者只会在输入表达式时等待,直到所有括号都关闭并以某种方式匹配。
我查看了方案中的引用,并在方案中使用了 try-catch 机制(如何在方案中实现 try-catch 块?) - 但这不起作用。我还在考虑在方案中实现我自己的算术表达式求值器版本,也许用括号作为分隔符。
我寻找一种评估任意表达式的方法,如果表达式无效,则从 eval 中获取诸如“无效表达式”之类的错误消息,并且不让读者等待右括号。
编辑:有关解决方案的实现,请参见下文。
解决方案
你的策略不会奏效。Scheme 有“try-catch”,但就像大多数编程语言中的“try-catch”一样,它只适用于运行时错误(程序运行时发生的错误)。相反,不平衡括号问题是语法错误(阅读程序时发生的错误)。
例如,在 Python 中,您可以编写:
try:
1 / 0
except:
pass
这会捕获错误,但不会捕获语法错误,例如:
try:
if
except:
pass
如果要允许输入具有不平衡的括号,则需要将输入作为字符串而不是语言本身的表达式。例如:
(define my-input "(+ 1 1")
很好,但是:
(define my-input (+ 1 1)
不是。
但是,在输入字符串上进行计算很烦人。因此,您应该做的下一步是将输入字符串标记化并将其解析为树。这也是您可以检测不平衡括号并报告错误的地方:
(define (parse input-string)
;; TODO
)
(parse "(+ 1 2)")
;; expect '(+ 1 2)
(parse "(+ 1 2")
;; expect an error: "not valid expression"
假设这parse
没有错误,那么您将拥有一棵树'(+ 1 2)
作为输出。下一步是编写一个使用树并产生答案的函数
(define (interp input-tree)
;; TODO
)
(interp '(+ 1 2))
;; expect 3
(interp '(+ (+ 5 6) 7))
;; expect 18
然后,您eval
只是parse
and的组合interp
:
(define (eval input-string)
(interp (parse input-string)))
(eval "(+ 1 2)")
;; expect 3
(eval "(+ 1 2")
;; expect an error: "not valid expression"
推荐阅读
- ios - 无法通过 fastlane 在 Crashlytics Beta 发行说明中包含表情符号
- exchangewebservices - 使用 ews soap 请求在线检查用户邮箱中是否存在特定文件夹
- c# - 如何在 umbraco 7.13 中动态地将 CSS 样式添加到 Grid 上的 div?
- c - 更改 C 中某些数组值的符号
- amazon-web-services - 使用 Boto3 从 AWS Cognito 检索数据
- javascript - HTML Javascript CSS ASP Classic - Loader Spinner 在 FIREFOX 中 POSTBACK 后不会停止
- r - 使用 na_if 将特定值替换为 NA
- python - 我们如何一次将嵌套的 json 对象反序列化为 python 模型对象?
- php - 等待 VirusTotal Scan 完成
- python - 在 Python 中指定时间段