我正在尝试使用Trifecta来解析一个非常简单的函数式语言,使用类似Haskell的布局语法.我正在处理Haddock文档和我对Parsec的经验,因为我找不到关于Trifecta本身的任何介绍性材料.
我遇到的问题是使用布局的东西,因为即使是Haddock文档也没有多大帮助.
给出以下代码:
import Text.Trifecta
import Text.Trifecta.Parser.Token.Style
import Text.Trifecta.Parser.Identifier.Style
import Text.Trifecta.Layout.Combinators
import Text.Trifecta.Language.Prim
import Control.Applicative
import Control.Monad.Trans
import Data.Maybe (fromMaybe)
import Data.HashSet as HashSet
import Data.ByteString.UTF8 as UTF8
-- Copypasta from Text.Trifecta.Parser.Identifier.Style
set :: [String] -> HashSet ByteString
set = HashSet.fromList . fmap UTF8.fromString
lang :: MonadParser m => LanguageDef m
lang = LanguageDef{ languageCommentStyle = haskellCommentStyle
, languageIdentifierStyle = emptyIdents{ styleReserved = set keywords }
, languageOperatorStyle = emptyOps{ styleReserved = set ops }
}
where
keywords = ["where"] …
Run Code Online (Sandbox Code Playgroud) 我正在使用Trifecta解析器组合库,我的解析器输出AST数据类型的实例.我希望每个实例都有唯一的ID(简单的Int).
在Parsec中,我会创建自定义状态并在neccesery时递增ID.我们怎样才能在Trifecta中做到这一点?
考虑一种完全可选分号的语言,几乎完全是糖,即:
;; foo; bar;;;;
已验证foo bar foobar
已验证if (+1); foo
与if (+1) foo
语义不同,因此;
不能被视为空格这是一个示例解析器:
{-# LANGUAGE OverloadedStrings #-}
import Text.Trifecta
import Text.Trifecta.Delta
import Text.PrettyPrint.ANSI.Leijen (putDoc, (<>), linebreak)
import Control.Monad.Trans.State.Strict
import Control.Applicative
type TestParser a = StateT Int Parser a
data AST a = Foo a | Bar a deriving (Show)
pFoo :: TestParser (AST (Delta, Int))
pFoo = curry Foo <$ string "foo" <*> position <* modify (+1) <*> get
pBar :: TestParser …
Run Code Online (Sandbox Code Playgroud) 我试图在Haskell中组合解析器,以便我可以解析某些模式n次.为了说明,想象一下我想从输入中解析最多八位数.我知道我可以使用count
从Text.Parser.Combinators
精确解析n个出现的,例如:
import Text.Parser.Char (digit)
import Text.Parser.Combinators (count)
eightDigits :: Parser [Char]
eightDigits = count 8 digit
Run Code Online (Sandbox Code Playgroud)
但是,如果它没有找到正好8位数,则会失败.我也可以some
用来解析一个或多个数字:
import Text.Parser.Char (digit)
import Text.Parser.Combinators (some)
someDigits :: Parser [Char]
someDigits = some digit
Run Code Online (Sandbox Code Playgroud)
上面的问题是它可能会消耗比我想要的更多的数字.最后,我可以使用try
,它结合了可能消耗输入的解析器,并且在失败时返回到它开始的位置:
import Text.Parser.Char (digit)
import Text.Parser.Combinators (count, try)
import Control.Applicative ((<|>))
twoOrThreeDigits :: Parser [Char]
twoOrThreeDigits = try (count 3 digit) <|> count 2 digit
Run Code Online (Sandbox Code Playgroud)
虽然这可以扩展到最多8次重复,但它不可扩展也不优雅,所以问题是我如何组合解析器来解析1到n次之间的模式?