我正在Clojure中实现一个中缀计算器,从我开始实现Dijkstra的分流码算法。我以为我把它弄得很好,但是笑话对我来说,它似乎根本不能很好地处理操作员。致电(shunting-yard "3 + 5")
=>
(\3)
。就这样。有人能告诉我这里处理操作员角色有什么问题吗?
(import '(java.lang.Character))
(defn operator? [sym]
"Determines if a given token is a mathematical operator."
(some #{sym} '(\+ \- \* \/ \% \^ \!)))
(defn associativity-of [operator]
"Determines the associativity of a given mathematical operator."
(if (some #{operator} '(\+ \- \* \/ \%))
'left
'right))
(defn precedence-of [operator]
"Determines the precedence of a given mathematical operator."
(case operator
(\+ \-) 2
(\* \/ \%) 3
(\^ \!) 4
0))
(defn operator-actions [stmt stack]
"Actions taken when the next token in the stmt is an operator."
(let [token-prec (precedence-of (first stmt))
token-assoc (associativity-of (first stmt))
stack-oper (first stack)
stack-prec (precedence-of stack-oper)]
(cond (or (and (= token-assoc 'left)
(<= token-prec stack-prec))
(and (= token-assoc 'right)
(< token-prec stack-prec)))
(cons stack-oper (shunt stmt (rest stack)))
:else (shunt (rest stmt) (cons (first stmt) stack)))))
(defn stack-operations [stack]
"Actions to take if (nil? stmt)"
(comment "If a left paren is found on the stack, it means
that there was no right paren to match it, and
therefore the statement had unbalanced parentheses.")
(cond (and (not (nil? stack))
(= (first stack) \()) (print "Unbalanced parentheses.\n")
(nil? stack) ()
:else (cons (first stack) (stack-operations (rest stack)))))
(defn shunt [stmt stack]
(cond (empty? stmt) (stack-operations stack)
(Character/isDigit (first stmt)) (cons (first stmt)
(shunt (rest stmt) stack))
(operator? (first stmt)) (operator-actions stmt stack)
(= (first stmt) \() (recur (rest stmt) (cons (first stmt) stack))
(= (first stmt) \)) (if (= (first stack) \()
(recur (rest stmt) (rest stack))
(cons (first stack) (shunt stmt (rest stack))))))
(defn shunting-yard [stmt]
(shunt stmt ()))
答案 0 :(得分:3)
我实际上并不知道Shunting-Yard算法(刚刚在维基百科中保存2分钟),但我看到的一个问题是shunt
不处理空格。因此它会读取您的\3
,递归和退出,因为下一个字符为\space
。如果stmt
没有空格,即"3+5"
,则会得到StackOverflowError
,但我认为这是进步。