括号如何与自定义数据类型一起使用?

时间:2019-10-11 13:08:07

标签: parsing haskell operators expression parentheses

目前,我正在研究在Haskell中解析和显示表达式的问题。

type Name = String
data Expr = Val Integer
          | Var Name
          | Expr :+: Expr
          | Expr :-: Expr
          | Expr :*: Expr
          | Expr :/: Expr
          | Expr :%: Expr

这是我的数据类型Expr的代码,这就是我定义show函数的方式:

instance Show Expr where
  show (Val x) = show x
  show (Var y) = y
  show (p :+: q) = par (show p ++ "+" ++ show q)
  show (p :-: q) = par (show p ++ "-" ++ show q)
  show (p :/: q) = par (show p ++ "/" ++ show q)
  show (p :*: q) = par (show p ++ "*" ++ show q)
  show (p :%: q) = par (show p ++ "%" ++ show q)

par :: String -> String
par s = "(" ++ s ++ ")"

稍后,我尝试将字符串输入转换为表达式,但是遇到以下问题:我不理解在Haskell中如何实现第二种情况下的括号。

*Main> Val 2 :*:Val 2 :+: Val 3 
((2*2)+3)
*Main> Val 2 :*:(Val 2 :+: Val 3) 
(2*(2+3))

因此,我对于如何将括号从字符串转换为表达式感到有些困惑。目前,我正在使用以下函数进行解析,但就目前而言,它只是忽略了括号,这不是预期的行为:

toExpr :: String -> Expr
toExpr str = f (lexer str) (Val 0)
   where 
    f [] expr = expr
    f (c:cs) expr
     |isAlpha (head c)  = f cs (Var c)
     |isDigit (head c)  = f cs (Val (read c))
     |c == "+"  = (expr :+: f cs (Val 0))
     |c == "-"  = (expr :-: f cs (Val 0))
     |c == "/"  = (expr :/: f cs (Val 0))
     |c == "*"  = (expr :*: f cs (Val 0))
     |c == "%"  = (expr :%: f cs (Val 0))
     |otherwise = f cs expr

编辑:少量语法错误

2 个答案:

答案 0 :(得分:2)

  

我不明白在第二种情况下括号是如何在Haskell中实现的。

方括号仅优先于要解析的表达式的特定部分。问题不在于您渲染的括号。我认为问题在于您没有 not 为您的运营商分配优先级。因此,这意味着,除非指定括号,否则Haskell将考虑所有运算符具有相同的优先级,并从左到右解析这些运算符。因此,这意味着 x y y z 被解析为(x y)⊗z

您可以使用:+:来定义:*infixl等运算符的优先级:

infixl 7 :*:, :/:, :%:
infixl 5 :+:, :-:

type Name = String
data Expr = Val Integer
          | Var Name
          | Expr :+: Expr
          | Expr :-: Expr
          | Expr :*: Expr
          | Expr :/: Expr
          | Expr :%: Expr

对于解析器(toExpr),您将需要一种像LALR parser [wiki]这样的解析机制,将结果存储在堆栈中,从而进行正确的操作。

答案 1 :(得分:1)

这是我的最终解析器,为我提供了所需的结果。为了得到结果,我想添加适当的语法,并根据他的语法写了一个语法分析。 谢谢大家的帮助。

strtok_to_array(varchar_col,hex_decode_string('00'))