首页 > 解决方案 > Scheme Lisp - 对任意算术表达式使用 eval

问题描述

我正在尝试使用 eval 在方案中评估任意和嵌套的算术表达式。表达式由数字、运算符、常量绑定和括号组成。例如,(eval (+ 1 1))(eval (+ (* 1 2) 3))

问题是,表达式也可能有不平衡的括号,比如 (eval ((+ 1 1)),scheme 中的读者只会在输入表达式时等待,直到所有括号都关闭并以某种方式匹配。

我查看了方案中的引用,并在方案中使用了 try-catch 机制(如何在方案中实现 try-catch 块?) - 但这不起作用。我还在考虑在方案中实现我自己的算术表达式求值器版本,也许用括号作为分隔符。

我寻找一种评估任意表达式的方法,如果表达式无效,则从 eval 中获取诸如“无效表达式”之类的错误消息,并且不让读者等待右括号。

编辑:有关解决方案的实现,请参见下文。

标签: schemelispracketeval

解决方案


你的策略不会奏效。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只是parseand的组合interp

(define (eval input-string)
  (interp (parse input-string)))

(eval "(+ 1 2)")
;; expect 3
(eval "(+ 1 2")
;; expect an error: "not valid expression"

推荐阅读