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

标签 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

编辑:一些语法错误

最佳答案

I don't understand how parentheses in the second case are implemented in Haskell.

括号只是优先考虑要解析的表达式的特定部分。问题不在于您呈现的括号。我认为问题在于您没有为运算符分配优先级。这意味着,除非您指定括号,Haskell 将认为所有运算符具有相同的优先级,并从左到右解析这些运算符。这意味着 x ⊕ 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] 这样的解析机制。将结果存储在堆栈上,从而进行正确的操作。

关于parsing - 括号如何与自定义数据类型一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58341959/

相关文章:

Javascript/jQuery - 使用正则表达式解析字符串中的主题标签,URL 中的 anchor 除外

ios - 在 iOS 中解析 moengage 通知响应时出现问题?

haskell - 为什么 GHC 不对 "No match in record selector"异常给出编译时警告?

Python 不等式 : ! = vs 不 ==

c++ - 冒号是什么意思(:) operator in "uint isWidget : 1;" in Qt?

javascript - 最小最大和 Javascript

java - Java 中的 Cookie 解析

python - 在 Python 中将小时和分钟转换为总分钟

c - 如何为递归类型创建 Storable 实例?

haskell - 带补集的快速幂集实现