在Haskell中实现抽象堆栈机

时间:2015-11-29 13:11:02

标签: haskell

我不知道什么是错的,但是当我尝试编译它时,它会说"解析输入错误'导出' &#34 ;.当我尝试删除deriving Show上的type Code时,错误将消失,但我无法使用翻译功能。为什么是这样?我还是很抱歉。

> module Imp where
>
> import Parsing
>
> type Ide = String
> data Imp
>   = Skip
>   | Assign Ide Imp
>   | Begin Imp
>   | Seq Imp Imp
>   | Ifz Imp Imp Imp
>   | While Imp Imp
>   | Num Int
>   | Var Ide
>   | Add Imp Imp
>   | Sub Imp Imp
>   | Mul Imp Imp
>   | Div Imp Imp
>   | Eq Imp Imp
>   deriving Show

> type Binding = (String, Int)

> data StackVal = N Int | Bind Binding deriving Show

> type Stack = [StackVal]

> type Env = [Binding]

> data ASM  --Abstract Stack Machine
>   = Push StackVal
>   | Pop StackVal
>   | ADD | SUB | MUL | DIV | EQUIV
>   | Jmp Int
>   | Jnz Int
>   | Lab Int
>   | Halt
>   deriving Show

> type Code = [ASM]




Translator
----------

> translate :: Imp -> Env -> Code
> translate (Num n) m               = [Push (N n)]
> translate (Var x) m               = [Push (Bind (x, v))] where Just v = lookup x m
> translate (Skip) m                = []   
> translate (Assign x exp) m        = translate exp m ++ [Pop (Bind (x, v))] where Just v = lookup x m
> translate (Seq c1 c2) m           = translate c1 m ++ translate c2 m
> translate (Ifz exp c1 c2) m       = translate exp m ++ [Jmp 1] ++ translate c1 m ++ [Jnz 2] 
>                                     ++ [Lab 1] ++ translate c2 m ++ [Lab 2]
> translate (While exp c) m         = [Lab 1] ++ translate exp m ++ [Jmp 2] ++ translate c m ++ [Jnz 1] ++ [Lab 2]
> translate (Add x y) m             = translate x m ++ translate y m ++ [ADD]
> translate (Sub x y) m             = translate x m ++ translate y m ++ [SUB]
> translate (Mul x y) m             = translate x m ++ translate y m ++ [MUL]
> translate (Div x y) m             = translate x m ++ translate y m ++ [DIV]
> translate (Eq x y) m              = translate x m ++ translate y m ++ [EQUIV]






Grammar
--------

> asgn :: Parser Imp
> asgn = eqimp +++ expr
>
> expr :: Parser Imp
> expr = addimp +++ subimp +++ term
>
> term :: Parser Imp
> term = mulimp +++ divimp +++ factor
>
> factor :: Parser Imp
> factor = (do symbol "("; e <- expr; symbol ")"; return e)
>   +++ number +++ idnt
>
> number :: Parser Imp
> number = (do n <- natural; return (Num n))
>
> idnt :: Parser Imp
> idnt = (do i <- identifier; return (Var i))
> 
> ide :: Parser Ide
> ide = (do i <- identifier; return (i))


Expressions
-----------

> eqimp :: Parser Imp
> eqimp = (do i <- idnt; symbol "="; a <- asgn; return (Eq i a))
>   +++ (do i <- idnt; symbol "="; e <- expr; return (Eq i e))
>   +++ (do i <- idnt; symbol "="; i <- idnt; return (Eq i i))
>   +++ (do e1 <- expr; symbol "="; e2 <- expr; return (Eq e1 e2))

> addimp :: Parser Imp
> addimp = (do t <- term; symbol "+"; e <- expr; return (Add t e))
>           +++ (do i <- idnt; symbol "+"; t <- term; return (Add i t))

> subimp :: Parser Imp
> subimp = (do t <- term; symbol "-"; e <- expr; return (Sub t e))
>           +++ (do i <- idnt; symbol "-"; t <- term; return (Sub i t))

> mulimp :: Parser Imp
> mulimp = (do f <- factor; symbol "*"; t <- term; return (Mul f t))
>           +++ (do i <- idnt; symbol "*"; f <- factor; return (Mul i f))

> divimp :: Parser Imp
> divimp = (do f <- factor; symbol "/"; t <- term; return (Div f t))
>           +++ (do i <- idnt; symbol "/"; f <- factor; return (Div i f))


Commands
---------

>
> skipimp :: Parser Imp
> skipimp = (do symbol "skip"; return Skip)
>
> assignimp :: Parser Imp
> assignimp = (do i <- ide; symbol ":="; e <- expr; return (Assign i e))
>
> assignimp2 :: Parser Imp
> assignimp2 = (do i <- ide; symbol ":="; e <- expr; symbol ";"; return (Assign i e))
>            +++ (do i <- ide; symbol ":="; e <- expr; return (Assign i e))
>
> seqimp :: Parser Imp
> seqimp = (do w <- whileimp; symbol ";"; s2 <- seqimp; return (Seq w s2))
>           +++ (do w <- whileimp; symbol ";"; c2 <- com3; return (Seq w c2))
>           +++ (do i <- ifzimp; symbol ";"; s2 <- seqimp; return (Seq i s2))
>           +++ (do i <- ifzimp; symbol ";"; c2 <- com3; return (Seq i c2))
>           +++ (do c1 <- com2; symbol ";"; s2 <- seqimp; return (Seq c1 s2))
>           +++ (do c1 <- com2; symbol ";"; c2 <- com2; symbol ";"; return (Seq c1 c2))
>           +++ (do c1 <- com2; symbol ";"; c2 <- com2; return (Seq c1 c2))
>
> ifzimp :: Parser Imp
> ifzimp =  (do symbol "if"; e <- expr; symbol "then"; c1 <- com;  
>                    symbol "else"; symbol "("; c2 <- com; symbol ")"; return (Ifz e c1 c2))
>        +++ (do symbol "if"; e <- expr; symbol "then"; c1 <- com; 
>                    symbol "else"; c2 <- com; return (Ifz e c1 c2))
>
> whileimp :: Parser Imp
> whileimp = (do symbol "while"; e <- expr; symbol "do"; 
>                       symbol "("; c2 <- com; symbol ")"; return (While e c2))
>           +++ (do symbol "while"; e <- expr;
>                       symbol "do"; c2 <- com; return (While e c2))
>
> beginimp :: Parser Imp
> beginimp = (do symbol "begin"; c <- com; symbol "end"; return (Begin c))
>
>
> com :: Parser Imp
> com = seqimp 
>       +++ whileimp 
>       +++ ifzimp 
>       +++ beginimp
>       +++ assignimp 
>       +++ skipimp
>       +++ (do symbol "("; c <- com; symbol ")"; return c)
>
> com2 :: Parser Imp
> com2 = beginimp
>       +++ whileimp 
>       +++ ifzimp 
>       +++ assignimp 
>       +++ skipimp
>       +++ (do symbol "("; c <- com2; symbol ")"; return c)
>
> com3 :: Parser Imp
> com3 = beginimp
>       +++ whileimp 
>       +++ ifzimp
>       +++ assignimp2 
>       +++ skipimp
>       +++ (do symbol "("; c <- com2; symbol ")"; return c)


Parsers
-------

> parse_imp :: String -> Imp
> parse_imp str =
>   case parse com str of
>       [(result, [])] -> result
>       [(_, out)] -> error ("unused input: " ++ out)
>       [] -> error ("invalid input: " ++ str)
>
> parse_exp :: String -> Imp
> parse_exp str =
>   case parse asgn str of
>       [(result, [])] -> result
>       [(_, out)] -> error ("unused input: " ++ out)
>       [] -> error ("invalid input: " ++ str)

更新:我删除了deriving Show部分的type Code。如果解析的输入不涉及变量,则translate函数似乎有效...例如:translate (parse_exp "1") []结果[Push (N 1)]。剩下的问题是,当我尝试类似translate (parse_exp "x + 1")之类的东西时,因为模式Just v的无效参数模式会出错。 translate (Assign x exp) m = ... where Just v = lookup x m上的那一行我猜有问题:

*Imp> translate (parse_exp "1 + 5") []
[Push (N 1), Push (N 5), ADD]
*Imp> translate (parse_exp "x + 1") []
[Push (Bind ("x",*** Exception: imp.lhs:50:66-84: Irrefutable pattern failed for pattern Just v

1 个答案:

答案 0 :(得分:2)

请注意,代码Just v = lookup x m仅在地图x中存在m引用的变量名称时才有效。但是,您的translate函数从不向环境添加变量,因此m始终为空,并且您的Assign代码将始终抛出异常。

解决方案?那取决于你的努力的具体细节,但我会添加一种方法来绑定变量,如lambda的。这不会使x +1解析,因为x仍然不在环境中,但如果您愿意,可以lambda x. x + 1进行解析。请注意,您需要弄清楚如何从堆栈中获取变量。