1
parsec-layout
を使用して、ハスケルのような構文で小さな言語を解析しようとしています。あまりにも互いに相互作用していないようだ二つの重要な機能は次のとおりです。F
とE
は用語がある場合Text.Parsec.Layoutを使用して並置ベースのインデントを認識する構文を解析する
- 機能アプリケーションの構文は、すなわち、並置され、
F E
はE
に適用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
このアプローチでは、 'caseBlock'(私が何か誤解していない限り' term1'を使う必要があります)を元に戻したいのであれば、解析は今 ' Xの 'のケース。 Xという言葉は現在の末尾のスペースを消費しないので、Xの ''に ''のアプリケーションとして解析されるので、私は推測します... – Cactus