作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Haskell Parsec 的 indents 包提供了一种解析缩进式语言(如 Haskell 和 Python)的方法。它重新定义了 Parser
类型,那么如何使用 Parsec 的 Text.Parsec.Token
导出的 token 解析器函数模块,它们是正常的Parser
类型?
背景
Text.ParserCombinators.Parsec.IndentParser
和 Text.ParserCombinators.Parsec.IndentParser.Token
Text.Parsec.Indent
newline
来自
Text.Parsec.Char
,它解析换行符)或解析器组合器(例如
count n p
来自
Text.Parsec.Combinator
,它运行解析器 p,n 次)
Text.Parsec.Token
想要导出由用户参数化的函数以及被解析语言的特征,例如,
braces p
函数将在解析 '{' 和解析 '}' 之前运行解析器 p,忽略诸如注释之类的内容,其语法取决于您的语言。
Text.Parsec.Token
的方式实现这一点的是它导出单个函数
makeTokenParser
,你调用它,给它你特定语言的参数(就像评论的样子),它返回一个记录,其中包含
Text.Parsec.Token
中的所有函数,适应您指定的语言。
Text.ParserCombinators.Parsec.IndentParser.Token
它看起来是
Text.Parsec.Token
的直接替代品.
Text.ParserCombinators.Parsec.IndentParser.Token
的模块, 它只提供
Text.Parsec.Indent
, 所以
我想知道如何从 Text.Parsec.Token
获取所有 token 解析器 (如
reserved "something"
解析保留关键字“something”,或如我之前提到的
braces
)。
Text.Parsec.Indent
通过某种单子(monad)状态魔法来计算源代码的列位是什么,因此它不需要像
whiteSpace
那样修改 token 解析器来自
Text.Parsec.Token
,这可能就是它不提供替换模块的原因。但是我遇到了类型问题。
Text.Parsec.Indent
,我所有的解析器都是
Parser Something
类型Something 是返回类型,
Parser
是 Text.Parsec.String 中定义的类型别名
type Parser = Parsec String ()
Text.Parsec.Indent
, 而不是导入
Text.Parsec.String
, 我用我自己的定义
type Parser a = IndentParser String () a
IndentParser String () Something
,其中 IndentParser 在 Text.Parsec.Indent 中定义。但是我从
makeTokenParser
获得的 token 解析器在
Text.Parsec.Token
是错误的类型。
Parser
的一个定义上面是另一个,但是当我尝试使用
Text.Parsec.Token
中的一个 token 解析器时,我得到编译错误
Couldn't match expected type `Control.Monad.Trans.State.Lazy.State
Text.Parsec.Pos.SourcePos'
with actual type `Data.Functor.Identity.Identity'
Expected type: P.GenTokenParser
String
()
(Control.Monad.Trans.State.Lazy.State Text.Parsec.Pos.SourcePos)
Actual type: P.TokenParser ()
最佳答案
你想做什么?
听起来您希望在任何地方都将解析器定义为类型Parser Something
(其中 Something 是返回类型)并通过隐藏和重新定义 Parser
来完成这项工作通常从 Text.Parsec.String
导入的类型或类似的。您仍然需要导入一些 Text.Parsec.String
,使 Stream 成为 monad 的实例;使用以下命令执行此操作:
import Text.Parsec.String ()
Parser
的定义是正确的。或者等效地(对于那些在评论中关注聊天的人)您可以使用
import Control.Monad.State
import Text.Parsec.Pos (SourcePos)
type Parser = ParsecT String () (State SourcePos)
import Text.Parsec.Indent (IndentParser)
在出现此定义的文件中。
Couldn't match expected type `State SourcePos' with actual type `Identity'
Expected type: P.GenTokenParser ...
Actual type: P.TokenParser ...
Text.Parsec.Token
“导入”解析器的位置, 你实际上做什么,当然(正如你简要提到的)首先定义一个记录你的语言参数,然后将它传递给函数
makeTokenParser
,它返回包含 token 解析器的记录。
import qualified Text.Parsec.Token as P
beetleDef :: P.LanguageDef st
beetleDef =
haskellStyle {
parameters, parameters etc.
}
lexer :: P.TokenParser ()
lexer = P.makeTokenParser beetleDef
P.LanguageDef st
只是一个
GenLanguageDef String st Identity
, 和
P.TokenParser ()
真的是
GenTokenParser String () Identity
.
import Control.Monad.State
import Text.Parsec.Pos (SourcePos)
import qualified Text.Parsec.Token as P
beetleDef :: P.GenLanguageDef String st (State SourcePos)
beetleDef =
haskellStyle {
parameters, parameters etc.
}
lexer :: P.GenTokenParser String () (State SourcePos)
lexer = P.makeTokenParser beetleDef
ParsecT String () (State SourcePos) Something
, 而不是
Parsec String () Something
(它是
ParsecT String () Identity Something
的别名),您的代码现在应该可以编译了。
Parser
类型,该文件与您定义实际解析器函数的文件分开并由该文件导入。因此两个重复的
import
语句。)
关于parsing - Haskell/Parsec : how do I use Text. Parsec.Token with Text.Parsec.Indent(来自 indents 包),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15315624/
我是一名优秀的程序员,十分优秀!