尝试将不匹配的括号设置为不正确的输入,在SML中不起作用

时间:2013-01-02 03:09:26

标签: parsing sml smlnj

我正在用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 *)

但是,当我尝试添加LparLpar2LparLpar3一起组成的规则时:

  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

我该如何解决?

1 个答案:

答案 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