我正在努力用 Common Lisp 自己写一些东西,实现调车场算法。我认为一切顺利,即使它出来时相当丑陋,如果我怀疑它的 Lispy 性,但在测试 REPL 中的函数后,我在标题中得到了错误。
代码如下,测试用例为(shunting-yard '(3 + 5))
。
(defparameter *output-queue* nil)
(defparameter *operator-stack* nil)
(defun determine-precedence (operator)
(case operator
(('+ '-) 2)
(('* '/) 3)
('^ 4)))
(defun shunting-yard (stmt)
(loop until (null stmt) do
(let ((token (car stmt)))
(cond ((or (numberp token)
(eq token '\())
(setf *output-queue* (cons token *output-queue*)))
((mapcar #'(lambda (x) (eq token x)) '(+ - * / ^))
(let* ((token-precedence (determine-precedence token))
(stack-topmost (car *operator-stack*))
(stack-precedence (determine-precedence stack-topmost)))
(when (< token-precedence stack-precedence)
(setf *output-queue* (cons stack-topmost *output-queue*))
(setf *operator-stack* (cdr *operator-stack*)))
(setf *operator-stack* (cons token *operator-stack*))))
((eq token '\))
(loop for stack-topmost in *operator-stack*
until (eq stack-topmost '\()
do (progn
(setf *output-queue* (cons stack-topmost *output-queue*))
(setf *operator-stack* (cdr *operator-stack*)))
finally (setf *operator-stack* (cdr *operator-stack*)))))
(setf stmt (cdr stmt))))
(loop while (not (null *operator-stack*))
do (progn
(setf *output-queue* (cons (car *operator-stack*) *output-queue*))
(setf *operator-stack* (cdr *operator-stack*))))
(nreverse *output-queue*))
错误是在代码本身(我的猜测)还是在我的测试用例中?
在此先感谢您,写这篇文章真的很有趣,我迫不及待地想做其他事情,但只有在我开始工作之后。
最佳答案
有几个错误:
首先:
(defun determine-precedence (operator)
(case operator
(('+ '-) 2)
(('* '/) 3)
('^ 4)))
报价需要去。全部。
第二个:
(mapcar #'(lambda (x) (eq token x)) '(+ - * / ^))
以上不是你想的那样。将其替换为对 MEMBER 的调用。
第三:
(when (< token-precedence stack-precedence)
您需要确保变量确实绑定(bind)到数字。 使用类似的东西
(check-type token-precedence number)
(check-type stack-precedence number)
之前作为检查。
愉快的进一步调试...
关于lisp - 口齿不清错误 : Expected-type: REAL datum: NIL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5163302/