我正在尝试使用Parsec解析Haskell中基于缩进的语言(想想Python,Haskell本身,Boo,YAML).我已经看过IndentParser库,看起来它是完美的匹配,但我无法弄清楚如何使我TokenParser成为缩进解析器.这是我到目前为止的代码:
import qualified Text.ParserCombinators.Parsec.Token as T
import qualified Text.ParserCombinators.Parsec.IndentParser.Token as IT
lexer = T.makeTokenParser mylangDef
ident = IT.identifier lexer
Run Code Online (Sandbox Code Playgroud)
这会引发错误:
parser2.hs:29:28:
Couldn't match expected type `IT.TokenParser st'
against inferred type `T.GenTokenParser s u m'
In the first argument of `IT.identifier', namely `lexer'
In the expression: IT.identifier lexer
In the definition of `ident': ident = IT.identifier lexer
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?我应该如何创建IT.TokenParser?或者IndentParser是否已被破坏并被避免?
我正在尝试从定期提供XML文件的网页获取股票市场报价(样本数据).XML的结构非常简单,如下所示:
<?xml version="1.0"?>
<Contents>
<StockQuote Symbol="PETR3" Date="21-12-2010" Time="13:20" Price="23.02" />
</Contents>
Run Code Online (Sandbox Code Playgroud)
(它不止于此,但这足以作为一个例子).
我想将它解析为数据结构:
data Quote = Quote { symbol :: String,
date :: Data.Time.Calendar.Day,
time :: Data.Time.LocalTime.TimeOfDay,
price :: Float}
Run Code Online (Sandbox Code Playgroud)
我或多或少地了解Parsec如何工作(在真实世界Haskell书的水平上),我尝试了一些Text.XML库,但我可以开发的是一个有效的代码,但对于这么简单的任务来说太大了,看起来像一个一半是黑客,而不是最好的.
我不知道了很多关于解析器和XML(我基本上知道我在RWH书中读到的东西,我从来没有使用解析器)(我只是做统计和数值编程,我不是一个计算机科学家).是否有一个XML解析库,我可以在其中告诉模型是什么并立即提取信息,而无需手工解析每个元素而无需解析纯字符串?
我正在考虑这样的事情:
myParser = do cont <- openXMLElem "Contents"
quote <- openXMLElem "StockQuote"
symb <- getXMLElemField "Symbol"
date <- getXMLElemField "Date"
(...)
closequote <- closeXMLElem "StockQuote"
closecont <- closeXMLElem "Contents"
return (symb, date)
results = parse myParser "" myXMLString
Run Code Online (Sandbox Code Playgroud)
我不需要处理纯字符串并自己创建组合器(我很擅长).
编辑:我可能需要阅读一些关于解析器(不仅是Parsec)和关于XML的最小值的解释(刚刚以正确的方式完成).你们推荐一些东西吗?
我必须解析的真正字符串是这样的:
stringTest = "<?xml …Run Code Online (Sandbox Code Playgroud) 我对Parsec的一个常见问题是,如果它出现在"正确"的位置,它往往会忽略无效输入.
作为一个具体的例子,假设我们有integer :: Parser Int,我写
expression = sepBy integer (char '+')
Run Code Online (Sandbox Code Playgroud)
(暂时忽略空白问题.)
这正确解析类似"123 + 456 + 789"的内容.但是,如果我喂它"123 + 456-789",它会愉快地忽略非法的" - "字符和表达式的尾部; 我实际上想要一条错误消息告诉我有关无效输入的信息,而不仅仅是让它无声地忽略该部分.
我明白为什么会这样; 我不确定的是如何解决它.设计使用所有提供的输入的解析器的一般方法是什么?只有当所有输入都是有效表达式时才能成功?
我试图使用ghc-7.10(RC 2)并在许多情况下得到此消息,例如,
src/Text/Regex/XMLSchema/Generic/RegexParser.hs:439:5:
Non type-variable argument
in the constraint: Text.Parsec.Prim.Stream s m Char
(Use FlexibleContexts to permit this)
When checking that ‘prop’ has the inferred type
prop :: forall s u (m :: * -> *) (t :: * -> *).
(Foldable t, Text.Parsec.Prim.Stream s m Char) =>
Char -> t Char -> Text.Parsec.Prim.ParsecT s u m [Char]
In an equation for ‘isCategory'’:
isCategory'
= (foldr1 (<|>) . map (uncurry prop)
$ [('L', "ultmo"), ('M', "nce"), ('N', "dlo"), ....])
<?> …Run Code Online (Sandbox Code Playgroud) 假设我想用语言X解析文件.真的,我只对其中的一小部分信息感兴趣.为此目的在Haskell的许多eDSL中编写解析器很容易(例如Megaparsec).
data Foo = Foo Int -- the information I'm after.
parseFoo :: Parsec Text Foo
parseFoo = ...
Run Code Online (Sandbox Code Playgroud)
这很容易产生一种功能getFoo :: Text -> Maybe Foo.
但现在我还要修改信息的来源Foo,即基本上我想实现
changeFoo :: (Foo -> Foo) -> Text -> Text
Run Code Online (Sandbox Code Playgroud)
与属性
changeFoo id ? id
getFoo . changeFoo f ? fmap f . getFoo
Run Code Online (Sandbox Code Playgroud)
可以通过将解析器的结果更改为类似镜头的方式来实现
parseFoo :: Parsec Text (Foo, Foo -> Text)
parseFoo = ...
Run Code Online (Sandbox Code Playgroud)
但是这使定义变得更加麻烦 - 我不能仅仅string掩盖不相关的信息,而是需要存储每个subparse 的匹配并手动重新组装它.
这可以通过将字符串重组保持在StateT解析器monad周围的层中来实现自动化,但我不能只使用现有的原始解析器.
这个问题是否有现成的解决方案?
我正在寻找一个好的ocaml解析库,它不是flex/bison的衍生物.理想情况下,我想要一个沿着parsec行的monadic组合库,但我找不到任何东西.
我会使用haskell,但为haskell制作llvm绑定比我原先想象的更加烦人.
干杯,
杜安
所有解析器Text.Parsec.Token礼貌地用于lexeme在令牌之后吃空格.对我来说不幸的是,空格包括新行,我想将它用作表达式终止符.有没有办法说服lexeme新线?
我最近使用Ply在Python中编写了一个解析器(它是yacc的python重新实现).当我差不多完成解析器时,我发现我需要解析的语法要求我在解析过程中进行一些查找以通知词法分析器.在没有查看通知词法分析器的情况下,我无法正确解析语言中的字符串.
鉴于我可以从语法规则控制词法分析器的状态,我想我将使用解析器模块中的查找表来解决我的用例,但是维护/测试可能变得太难了.所以我想了解一些其他选择.
在Haskell中,我会使用Parsec,一个解析函数库(称为组合器).是否有Parsec的Python实现?或者也许其他一些生产质量库充满了解析功能,所以我可以在Python中构建一个上下文敏感的解析器?
编辑:我在上下文免费解析的所有尝试都失败了.出于这个原因,我不认为ANTLR在这里有用.
在一个阶段中混合词法分析器和解析阶段有时会使Parsec解析器的可读性降低,但也会降低它们的速度.一种解决方案是使用Alex作为标记化器,然后使用Parsec作为标记流的解析器.
这很好但是如果我能摆脱Alex会更好,因为它在编译管道中添加了一个预处理阶段,与haskell"IDE"等没有很好地集成.我想知道是否有这样的事情用于描述标记器的haskell EDSL,非常符合Alex的风格,但是作为库.
我正在尝试学习如何Parsec编写Delphi解析器,但我在定义LanguageDef时遇到困难.
在Delphi中,有两种类型的注释块,(* comments *)和{ comments }.但是LanguageDef的commentStart和commentEnd的类型是String,而不是[String],所以我只能放入一个或另一个.
所以,我尝试制作自己的whiteSpace解析器,但我不确定我是否真的可以将其传入makeTokenParser.
任何帮助,将不胜感激.
谢谢
约翰和克里斯都帮助我了解和解决问题搞定了,但解决的办法包括更换该解析器的大量makeTokenParser提供,所以它不是完全不可取的.
如果我能找到更好的解决方案,我会再次发帖.