2016-05-07 3 views
1

parsec-layoutを使用して、ハスケルのような構文で小さな言語を解析しようとしています。あまりにも互いに相互作用していないようだ二つの重要な機能は次のとおりです。FEは用語がある場合Text.Parsec.Layoutを使用して並置ベースのインデントを認識する構文を解析する

  • 機能アプリケーションの構文は、すなわち、並置され、F EEに適用Fための構文です。インデントは、次の2つ、つまり、ネストを示すために使用することができます
  • は等価です。

    X = case Y of 
        A -> V 
        B -> W 
    
    X = case Y of A -> V; B -> W 
    
私は私が解析できるようになる空白をスキップして保つの組み合わせを把握するために管理していない

そのような定義のリスト私はrunP (laidout binding) s経由

s = unlines [ "A = case B of" 
      , " X -> Y Z" 
      , "C = D" 
      ] 

のように入力にそれを実行しようとした場合、それはアプリケーションY Zに失敗し、

import Text.Parsec hiding (space, runP) 
import Text.Parsec.Layout 
import Control.Monad (void) 

type Parser = Parsec String LayoutEnv 

data Term = Var String 
      | App Term Term 
      | Case Term [(String, Term)] 
      deriving Show 

name :: Parser String 
name = spaced $ (:) <$> upper <*> many alphaNum 

kw :: String -> Parser() 
kw = void . spaced . string 

reserved :: String -> Parser() 
reserved s = try $ spaced $ string s >> notFollowedBy alphaNum 

term :: Parser Term 
term = foldl1 App <$> part `sepBy1` space 
    where 
    part = choice [ caseBlock 
        , Var <$> name 
        ] 

    caseBlock = Case <$> (reserved "case" *> term <* reserved "of") <*> laidout alt 

    alt = (,) <$> (name <* kw "->") <*> term 

binding :: Parser (String, Term) 
binding = (,) <$> (name <* kw "=") <*> term 

-- https://github.com/luqui/parsec-layout/issues/1 
trim :: String -> String 
trim = reverse . dropWhile (== '\n') . reverse 

runP :: Parser a -> String -> Either ParseError a 
runP p = runParser (p <* eof) defaultLayoutEnv "" . trim 

::私が変更された場合、

(line 2, column 10): 
expecting space or semi-colon 

しかしここに私の単純化されたコードですterm

term = foldl1 App <$> many1 part 

は、それはそう、私は問題はすでにそのnameに関係していると思います

(line 3, column 4): 
expecting semi-colon 

答えて

1

につながる、(インデントせ!)第三行の先頭に用語を解析停止、次のスペースを排除していませんtermの定義のsepBy1は表示されません。そして

term0 = foldl1 App <$> (Var <$> name) `sepBy1` space 

term1 = foldl1 App <$> (Var <$> name') `sepBy1` space 

name' = (:) <$> upper <*> many alphaNum 

term3 = foldl1 App <$> many (Var <$> name) 

runP term0 "A B C" -- fails 
runP term1 "A B C" -- succeeds 
runP term3 "A B C" -- succeeds 

私は溶液の一部を定義することであると思うname'が上記のようである

part = [ caseBlock, Var <$> name' ] 

termこれらの簡略バージョンを考えます。しかし、まだいくつかの問題があります。

+0

このアプローチでは、 'caseBlock'(私が何か誤解していない限り' term1'を使う必要があります)を元に戻したいのであれば、解析は今 ' Xの 'のケース。 Xという言葉は現在の末尾のスペースを消費しないので、Xの ''に ''のアプリケーションとして解析されるので、私は推測します... – Cactus

関連する問題