无法与Proc Parser中的预期类型匹配

时间:2017-04-09 09:12:44

标签: haskell

我正在尝试为Proc语言编写解析器,这是While语言的扩展版本。完成后,它应该能够输入如下:

"/*fac_loop (p.23)*/\ny:=1;\nwhile !(x=1) do (\n y:=y*x;\n x:=x-1\n)"

并生产:

(Comp (Ass "y" (N 1)) (While (Neg (Eq (V "x") (N 1))) (Comp (Ass "y"
       (Mult (V "y") (V "x"))) (Ass "x" (Sub (V "x") (N 1))))))

我已经获得了Aexp,Bexp和Stm的语法以及我无法改变的Num,Var,Pname,DecV和DecV的类型。我的Haskell代码如下:

module SecondAttempt where

import System.IO
import Control.Monad
{-# LANGUAGE StandaloneDeriving #-}
import Text.Megaparsec
import Text.Megaparsec.String
import Data.List (intercalate)


import Prelude hiding (Num)
import qualified Prelude (Num)

--- Proc definition

-- S ::= x:=a
--    | skip
--    |S1 ;S2
--    | if b then S1 else S2
--    | while b do S
--    | begin Dv Dv S end
--    | call p
-- Dv ::= var x := a ; DV | ε
-- Dp ::= proc p is S ; DP | ε

--- Types

type Num   = Integer
type Var   = String
type Pname = String
type DecV  = [(Var,Aexp)]
type DecP  = [(Pname,Stm)]

--- Data structures

data Aexp = N Num
          | V Var
          | Mult Aexp Aexp
          | Add Aexp Aexp
          | Sub Aexp Aexp

data Bexp = TRUE
          | FALSE
          | Neg Bexp
          | And Bexp Bexp
          | Le Aexp Aexp
          | Eq Aexp Aexp

data Stm = Skip
          | Ass Var Aexp
          | Comp Stm Stm
          | If Bexp Stm Stm
          | While Bexp Stm
          | Block DecV DecP Stm
          | Call Pname

--- Parser Preliminaries

cr :: Parser [Char]
cr = many (oneOf "\r\n")

tok :: String -> Parser String
tok t = string t <* whitespace

whitespace :: Parser ()
whitespace = many (oneOf " \t") *> pure ()

--- Parser

aexp :: Parser Aexp
aexp =  N     <$ tok "N" <*> num
    <|> V     <$ tok "V" <*> var
    <|> Mult  <$ tok "Mult" <*> aexp <* tok "*" <*> aexp
    <|> Add   <$ tok "Add" <*> aexp <* tok "+" <*> aexp
    <|> Sub   <$ tok "Sub" <*> aexp <* tok "-" <*> aexp

bexp :: Parser Bexp
bexp =  TRUE  <$ tok "TRUE"
    <|> FALSE <$ tok "FALSE"
    <|> Neg   <$ tok "Neg" <* tok "!" <*> bexp
    <|> And   <$ tok "And" <*> bexp <* tok "&" <*> bexp
    <|> Le    <$ tok "Le" <*> aexp <* tok "<=" <*> aexp
    <|> Eq    <$ tok "Eq" <*> aexp <* tok "=" <*> aexp

stm :: Parser Stm
stm =   Ass   <$ tok "Ass" <*> var <* tok ":=" <*> aexp
    <|> Comp  <$ tok "Comp" <*> stm <* tok ";" <*> stm
    <|> Skip  <$ tok "Skip"
    <|> If    <$ tok "If" <*> bexp <* tok "then" <*> stm <* tok "else" <*> stm
    <|> While <$ tok "While" <*> bexp <* tok "do" <*> stm
    <|> Block <$ tok "begin" <*> decv <*> decp <*> stm <* tok "end"
    <|> Call  <$ tok "call" <*> pname

num :: Parser Num
num = (some (oneOf ['0' .. '9']) >>= return . read) <* whitespace

var :: Parser Var
var = tok "\"" *> some (noneOf ("\n\r\"")) <* tok "\""

decv :: Parser DecV
decv = var <* tok ":=" <*> aexp <* tok ";" <*> decv

decp :: Parser DecP
decp = pname <* tok "is" <*> stm <* tok ";" <*> decp

pname :: Parser Pname
pname = tok "\"" *> some (noneOf ("\n\r\"")) <* tok "\""

true :: Bool
true = True

false :: Bool
false = False

我收到两个类型错误,每个错误都与我的decv和decp函数有关:

Couldn't match type ‘[Char]’ with ‘Aexp -> DecV -> DecV’
    Expected type: ParsecT
                     Dec String Data.Functor.Identity.Identity (Aexp -> `DecV -> DecV)
      Actual type: Parser Var
    In the first argument of ‘(<*)’, namely ‘var’
    In the first argument of ‘(<*>)’, namely ‘var <* tok ":="’

Couldn't match type ‘[Char]’ with ‘Stm -> DecP -> DecP’
    Expected type: ParsecT
                     Dec String Data.Functor.Identity.Identity (Stm -> DecP -> DecP)
      Actual type: Parser Pname
    In the first argument of ‘(<*)’, namely ‘pname’
    In the first argument of ‘(<*>)’, namely ‘pname <* tok "is"’

真的不知道怎么解决这个问题!

1 个答案:

答案 0 :(得分:1)

问题是您没有正确地为列表(DecVDecP)创建解析器。

对于DecV,您需要先将varaexp成对,然后再将其列为清单。

而不是:

decv :: Parser DecV
decv = var <* tok ":=" <*> aexp <* tok ";" <*> decv

decp :: Parser DecP
decp = pname <* tok "is" <*> stm <* tok ";" <*> decp

怎么样:

decv :: Parser DecV
decv = many ((,) <$> var <* tok ":=" <*> aexp <* tok ";")

decp :: Parser DecP
decp = many ((,) <$> pname <* tok "is" <*> stm <* tok ";")