我正在用SML编写一个计算器。
在我的程序中,我使用下面的括号:
{ } (* highest priority *)
[ ] (* middle priority *)
( ) (* weakest priority *)
当用户输入如下字符串时:
calc "1+(2*3)" (* that's ok *)
但那些:
calc "1+[2*3)" (* Not Ok *)
calc "1+(2*3}" (* Not Ok *)
calc "1+{2*3]" (* Not Ok *)
不是,因为打开的括号与其右括号不匹配。
我试着在SML中编写它,但它不起作用。当用户输入时我想做什么
带有不平衡括号的表达式,是返回-1
或显示错误消息
以下是代码:
signature ScannerForExp = sig
datatype token =
(* parenthesis *)
Lpar3 (* { *)
| Rpar3 (* } *)
| Lpar2 (* [ *)
| Rpar2 (* ] *)
| Lpar (* ( *)
| Rpar (* ) *)
(* operations *)
| Multiply (* * *)
| Div (* / *)
| Plus (* + *)
| Minus (* - *)
| Modulo (* % *)
| Power (* ^ *)
| Num of int (* [0-9]+ *)
| Undef of string (* undefined *)
val scanner : string -> (token list)
end;
| #"{"::r => if s = "" then (Lpar3,r) else (toToken s,c::l)
| #"}"::r => if s = "" then (Rpar3,r) else (toToken s,c::l)
| #"["::r => if s = "" then (Lpar2,r) else (toToken s,c::l)
| #"]"::r => if s = "" then (Rpar2,r) else (toToken s,c::l)
| #"("::r => if s = "" then (Lpar,r) else (toToken s,c::l)
| #")"::r => if s = "" then (Rpar,r) else (toToken s,c::l)
这是处理这个问题的函数:
fun E l = E2 l
and F l
= case l of
(Num n)::l1 => (NumNode n,l1)
| Lpar::l1 => let val (en,l2) = E l1 in case l2 of Rpar::l3 => (en,l3)
| Lpar2::l1 => let val (en,l2) = E l1 in case l2 of Rpar2::l3 => (en,l3)
| Lpar3::l1 => let val (en,l2) = E l1 in case l2 of Rpar3::l3 => (en,l3)
...
...
(* more code *)
但是,当我尝试添加Lpar
与Lpar2
或Lpar
与Lpar3
一起组成的规则时:
fun E l = E2 l
and F l
= case l of
(Num n)::l1 => (NumNode n,l1)
| Lpar::l1 => let val (en,l2) = E l1 in case l2 of Rpar::l3 => (en,l3)
| Lpar2::l1 => let val (en,l2) = E l1 in case l2 of Rpar2::l3 => (en,l3)
| Lpar3::l1 => let val (en,l2) = E l1 in case l2 of Rpar3::l3 => (en,l3)
(* a ( with a ] *)
| Lpar::l1 => let val (en,l2) = E l1 in case l2 of Rpar2::l3 => raise exception
我明白了:
stdIn:5875.9-5903.34 Error: match redundant and nonexhaustive
我该如何解决?
答案 0 :(得分:1)
您的缩进有点偏,但看起来您已经获得的代码应该在括号不匹配时引发ParserForExp
异常。
使用“新”代码时,会发生错误,因为您有两个Lpar::l1
个案例,这使得其中一个案件变得多余。
我相信你需要移动不匹配的括号案例:
| Lpar::l1 => let val (en,l2) = E l1 in
case l2 of Rpar::l3 => (en,l3)
| Rpar2::l3 => [raise mismatched parentheses]
| Rpar3::l3 => [raise mismatched parentheses]
| _ => raise ParserForExp
end