【问题标题】:Haskell - Happy, math expressions and variables parserHaskell - Happy,数学表达式和变量解析器
【发布时间】:2013-05-30 00:12:27
【问题描述】:

我正在开发一个快乐的数学表达式和变量解析器。问题是我不知道如何保存变量的值并在以后使用它。有什么想法吗?

这是我识别表达式和变量赋值的方式:

genExp   : exp                    { $1 }
         | variable '=' exp            { //here I want to save the value of the variable; something like this: insert variables $1 $3, where 'variables' is a Data.Map }

一个表达式可以包含一个变量。例如:

a = 2 + 1
a + 2 (now the parser must print 5)

我需要在解析器解析行'a = 2 + 1'时保存变量'a'的值,并在解析器解析行'a +时获取变量'a'的值2'

【问题讨论】:

  • 呃,这个问题不是很清楚。你能改写一下吗?代码示例和您尝试解决的实际问题也会很棒。谢谢。
  • 我编辑了我的问题。

标签: parsing haskell functional-programming happy


【解决方案1】:

您要做的是在表达式的求值期间而不是在解析期间跟踪变量的值。假设您将表达式解析为以下类型:

data Expr = Literal Int | Variable Var | Assign Var Expr | Add Expr Expr | ...
newtype Var = Var String deriving (Ord, Eq, Show)

然后您可以简单地在评估函数周围传递一个包含所有变量当前值的 Map:

import qualified Data.Map as M
import Control.Monad.State

data Expr = Literal Int | Variable Var | Assign Var Expr | Add Expr Expr
newtype Var = Var String deriving (Ord, Eq, Show)

-- Each Expr corresponds to a single line in your language, so
-- a = 2+1
-- a + 2
-- corresponds to
-- [Assign (Var "a") (Add (Literal 2) (Literal 1)),
--  Add (Variable (Var "a")) (Literal 2)]
eval :: [Expr] -> Int
eval es = last $ evalState (mapM eval' es) M.empty -- M.empty :: M.Map Var Int
  where
    eval' (Literal n)  = return n
    eval' (Variable v) = do
      vs <- get
      case M.lookup v vs of
        Just x -> return x
        _      -> error $ "variable " ++ show v ++ " is undefined!"
    eval' (Assign v ex) = do
      x <- eval' ex
      modify (M.insert v x)
      return x
    eval' (Add a b) = do
      x <- eval' a
      y <- eval' b
      return (x+y)

当然,没有什么可以阻止您在解析表达式时对表达式求值,从而无需像这样的抽象语法树。那里的总体思路是一样的。在整个解析过程中,您需要保留一些状态,以跟踪所有变量的当前值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多