我刚刚开始使用Parsec(在Haskell方面经验不足),而且我对使用monads或applicatives感到有些困惑.阅读"真实世界Haskell","写你一个Haskell"之后的整体感觉以及这里的一个问题是应用程序是首选,但我真的不知道.
所以我的问题是:
使用Control.Applicative对Parsec非常有用,但是你需要始终隐藏<|>和类似的对象,因为它们与Parsec自己的冲突:
import Control.Applicative hiding ((<|>), many, optional)
import Text.Parsec.Combinator
import Text.Parsec
Run Code Online (Sandbox Code Playgroud)
或者,正如Antal SZ指出的那样,您可以隐藏Parsec版本.但是,据我所知,这似乎是一个不必要的限制.
为什么parsec不是简单地从Applicative实现这些运算符?
该缩进包Haskell的秒差距提供了一种方法来解析缩进式语言(比如Haskell和Python).它重新定义了Parser类型,那么如何使用Parsec Text.Parsec.Token模块导出的令牌解析器函数,这些函数属于普通Parser类型?
Text.ParserCombinators.Parsec.IndentParser和Text.ParserCombinators.Parsec.IndentParser.TokenText.Parsec.IndentParsec附带了大量模块.他们中的大多数导出一堆有用的解析器(例如newlinefrom Text.Parsec.Char,解析换行符)或解析器组合器(例如, count n p从Text.Parsec.Combinator,运行解析器p,n次)
但是,该模块Text.Parsec.Token希望导出由用户参数化的函数和正在解析的语言的特征,例如,该braces p函数将在解析'{'之后和解析'}'之前运行解析器p,忽略评论之类的东西,其语法取决于你的语言.
Text.Parsec.Token实现这一目标的方法是它导出一个函数makeTokenParser,你调用它,给它你特定语言的参数(就像评论的样子),并返回一个包含所有函数的记录Text.Parsec.Token,适合你的语言.指定.
当然,在缩进式语言中,这些需要进一步调整(也许?这里是我不确定的地方 - 我稍后会解释)所以我注意到(可能是过时的)IndentParser包提供了一个模块Text.ParserCombinators.Parsec.IndentParser.Token这看起来是替补Text.Parsec.Token.
我应该在某些时候提到所有Parsec解析器都是monadic函数,所以它们用状态做神奇的事情,这样错误消息可以说出源文件中的哪一行和哪一行出现了错误
由于一些小的原因,在我看来,缩进包或多或少是当前版本的IndentParser,但它没有提供看起来像Text.ParserCombinators.Parsec.IndentParser.Token它只提供的模块Text.Parsec.Indent,所以我想知道如何获得所有的令牌解析器Text.Parsec.Token(比如reserved "something"解析保留的关键字"something",或者braces我之前提到过的).
这样看来,我认为(新) …
我正在使用Parsec解析表达式,我想使用Parsec中的用户状态跟踪这些表达式中的变量.不幸的是我真的没办法怎么做.
给出以下代码:
import Data.Set as Set
inp = "$x = $y + $z"
data Var = V String
var = do char '$'
n <- many1 letter
let v = Var n
-- I want to modify the set of variables here
return v
parseAssignment = ... -- parses the above assignment
run = case runIdentity $ runParserT parseAssignment Set.empty "" inp of
Left err -> ...
Right -> ...
Run Code Online (Sandbox Code Playgroud)
所以,uin ParsecT s u m a会Set.Set …
我正在尝试将这个简单的parsec代码编译
import Text.Parsec
simple = letter
Run Code Online (Sandbox Code Playgroud)
但我一直收到这个错误
No instance for (Stream s0 m0 Char)
arising from a use of `letter'
Possible fix: add an instance declaration for (Stream s0 m0 Char)
In the expression: letter
In an equation for `simple': simple = letter
Run Code Online (Sandbox Code Playgroud) 我将编写一个verilog(或vhdl)语言的解析器,并将对解析数据进行大量操作(某种转换).我打算解析真正的大文件(完整的Verilog设计,大到10K行),我最终会支持大部分的Verilog.我不介意输入,但每当我添加对其他规则的支持时,我不想重写代码的任何部分.
在Haskell,你会推荐哪个图书馆?我知道Haskell并且之前使用过Happy(玩).我觉得有可能使用Parsec来转换代码中的解析字符串(这是一个很好的加分).我没有使用uu-paringlib的经验.
那么要解析verilog/VHDL的全语法,推荐其中一个?我主要担心的是我可以随心所欲地操纵解析数据的简易性和"正确性".速度不是主要问题.
文档Parsec.Expr.buildExpressionParser说:
相同优先级的前缀和后缀运算符只能出现一次(如果 - 是前缀否定,则不允许--2).
事实上,这是咬我的,因为我试图解析的语言允许任意重复它的前缀和后缀运算符(想想像C表达式**a[1][2]).
那么,为什么要Parsec制定这个限制,我该如何解决呢?
我想我可以将我的前缀/后缀解析器移到term解析器中,因为它们具有最高优先级.
即
**a + 1
Run Code Online (Sandbox Code Playgroud)
被解析为
(*(*(a)))+(1)
Run Code Online (Sandbox Code Playgroud)
但是如果我想要解析它,我该怎么办?
*(*((a)+(1)))
Run Code Online (Sandbox Code Playgroud)
如果buildExpressionParser做了我想要的,我可以简单地重新排列表中运算符的顺序.
注意请参阅此处以获得更好的解决方
我正在用Parsec写我的第一个程序.我想解析MySQL模式转储,并想提出一种很好的方法来解析表示某些关键字的字符串,不区分大小写.下面是一些代码,显示了我用来解析"CREATE"或"create"的方法.有一个更好的方法吗?不使用buildExpressionParser的答案是最好的.我在这里采取婴儿步骤.
p_create_t :: GenParser Char st Statement
p_create_t = do
x <- (string "CREATE" <|> string "create")
xs <- manyTill anyChar (char ';')
return $ CreateTable (x ++ xs) [] -- refine later
Run Code Online (Sandbox Code Playgroud) 我有一个279MB的文件,包含大约1000万个键/值对,大约有500,000个唯一键.它按键分组(每个键只需要写一次),因此给定键的所有值都在一起.
我想要做的是转换关联,创建一个文件,其中对按值分组,给定值的所有键都存储在一起.
目前,我正在使用Parsec作为元组列表读取对(K,[V])(使用惰性IO,因此我可以在Parsec处理输入文件时将其作为流处理),其中:
newtype K = K Text deriving (Show, Eq, Ord, Hashable)
newtype V = V Text deriving (Show, Eq, Ord, Hashable)
tupleParser :: Parser (K,[V])
tupleParser = ...
data ErrList e a = Cons a (ErrList e a) | End | Err e
parseAllFromFile :: Parser a -> FilePath-> IO (ErrList ParseError a)
parseAllFromFile parser inputFile = do
contents <- readFile inputFile
let Right initialState = parse getParserState inputFile contents
return $ loop initialState
where loop …Run Code Online (Sandbox Code Playgroud)