2017-04-13 1 views
1

필자는 While 언어의 확장 버전 인 Proc 언어에 대한 파서를 작성하려고합니다.파서는 터미널에서 아무것도 반환하지 않습니다.

"/*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의 문법을 주어졌다, Pname, DecV 및 DecV는 변경할 수 없습니다. 내 하스켈 코드는 다음과 같습니다 :

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) 


-- 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 | ε 

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 
      deriving (Show, Eq, Read) 


data Bexp = TRUE 
      | FALSE 
      | Neg Bexp 
      | And Bexp Bexp 
      | Le Aexp Aexp 
      | Eq Aexp Aexp 
      deriving (Show, Eq, Read) 


data Stm = Skip 
      | Ass Var Aexp 
      | Comp Stm Stm 
      | If Bexp Stm Stm 
      | While Bexp Stm 
      | Block DecV DecP Stm 
      | Call Pname 
      deriving (Show, Eq, Read) 


--- 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() 

whileParser :: Parser Stm 
whileParser = whitespace >> stm 

--- 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 = ifStm 
    <|> whileStm 
    <|> skipStm 
    <|> assStm 
    <|> compStm 
    <|> blockStm 
    <|> callStm 

ifStm :: Parser Stm 
ifStm = 
    do tok "if" 
    cond <- bexp 
    tok "then" 
    stm1 <- stm 
    tok "else" 
    stm2 <- stm 
    return $ If cond stm1 stm2 

whileStm :: Parser Stm 
whileStm = 
    do tok "while" 
    cond <- bexp 
    tok "do" 
    stm <- stm 
    return $ While cond stm 

assStm :: Parser Stm 
assStm = 
    do var <- var 
    tok ":=" 
    expr <- aexp 
    return $ Ass var expr 

skipStm :: Parser Stm 
skipStm = tok "skip" >> return Skip 

compStm :: Parser Stm 
compStm = 
    do stm1 <- stm 
    tok ";" 
    stm2 <- stm 
    return $ Comp stm1 stm2 

blockStm :: Parser Stm 
blockStm = 
    do tok "begin" 
    decv <- decv 
    decp <- decp 
    stm <- stm 
    tok "end" 
    return $ Block decv decp stm 

callStm :: Parser Stm 
callStm = 
    do tok "call" 
    pname <- pname 
    return $ Call pname 

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

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

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

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

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

true :: Bool 
true = True 

false :: Bool 
false = False 

parseString :: String -> Stm 
parseString str = 
    case parse whileParser "" str of 
    Left e -> error $ show (parseErrorPretty e) 
    Right r -> r 

이 잘 컴파일하지만 나는 그런 'parseString을 같은 명령을 실행할 때 "X = 1"프로그램이 ghci에로드되면, 그냥 달려과에 아무것도 출력하지 않습니다 터미널. 어떤 아이디어? x이 파서에 따른 유효한 변수 이름이없는 것처럼

답변

0
var = tok "\"" *> some (noneOf ("\n\r\"")) <* tok "\"" <* whitespace 

그것은 보이는 따라서 x:=1는 할당 아니다.

대신 변수 이름은 "x" 일 수 있습니다. parseString "\"x\":=1"과 같은 것을 시도해보고 무슨 일이 일어나는 지보십시오.

+0

내가 맨 위에서 준 예제는 작동해야하는 것이므로, x를 잘못 정의하여 ""주위에서 만 작동하므로 내'var' 함수가 올바르지 않습니까? "parseString"\ "x \": = 1 "'을 시도하고 'Exception : 1 : 6 : \ n 예기치 않은'1 '\ n 추가 \"추가 \ ","Mult \ ", \"Sub \ ","N "또는 'V'\ n"' –

+0

@datguywelbz 예, 파서는 x 주위에 따옴표가 필요합니다. 또한 상단에있는 예제와 대응하는 표현식 앞에 Add 등이 필요합니다. – chi

관련 문제