首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用最新版本的Parsec.Indent库?

如何使用最新版本的Parsec.Indent库?
EN

Stack Overflow用户
提问于 2021-06-25 20:26:44
回答 1查看 50关注 0票数 1

这个问题似乎是this question的翻版,然而,自2012年以来,Parsec或缩进库都发生了变化,我为indent库找到的旧示例都没有编译到最新版本。

我想为一种编程语言制作一个解析器,其中缩进是语法的一部分(用于指示作用域),为了实现这一点,我想使用Text.Parsec.Indent库,但我对如何使用它感到困惑。对我来说,很明显,必须进行一些修改/自定义解析器类型,但我对State monad的有限了解和对parsec的表面理解似乎还不够。

假设您想为一个简单的int列表创建一个解析器,如下所示。如何做到这一点呢?

代码语言:javascript
运行
复制
mylist
    fstitem
    snditem

我试图基于互联网上流传的一些老例子创建一个简单的解析器,看起来像这样,但它显然会产生一些类型错误:

代码语言:javascript
运行
复制
import Control.Monad.State

import Text.Parsec hiding (State)
import Text.Parsec.Indent
import Text.Parsec.Pos

type IParser a = ParsecT String () (State SourcePos) a

parseInt :: IParser Integer
parseInt = read <$> many1 digit

parseIndentedInt :: IParser Integer
parseIndentedInt = indented *> parseInt

具体地说:

代码语言:javascript
运行
复制
Frontend/Parser.hs:14:20: error:
    • Couldn't match type ‘Control.Monad.Trans.Reader.ReaderT
                             Text.Parsec.Indent.Internal.Indentation m0’
                     with ‘StateT SourcePos Data.Functor.Identity.Identity’
      Expected type: IParser Integer
        Actual type: ParsecT String () (IndentT m0) Integer
    • In the expression: indented *> parseInt
      In an equation for ‘parseIndentedInt’:
          parseIndentedInt = indented *> parseInt
   |
14 | parseIndentedInt = indented *> parseInt
   |                    ^^^^^^^^^^^^^^^^^^^^

Frontend/Parser.hs:14:32: error:
    • Couldn't match type ‘StateT
                             SourcePos Data.Functor.Identity.Identity’
                     with ‘Control.Monad.Trans.Reader.ReaderT
                             Text.Parsec.Indent.Internal.Indentation m0’
      Expected type: ParsecT String () (IndentT m0) Integer
        Actual type: IParser Integer
    • In the second argument of ‘(*>)’, namely ‘parseInt’
      In the expression: indented *> parseInt
      In an equation for ‘parseIndentedInt’:
          parseIndentedInt = indented *> parseInt
   |
14 | parseIndentedInt = indented *> parseInt
   |                                ^^^^^^^^
Failed, no modules loaded.
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-25 22:04:11

好的,在深入研究了源代码并查看了缩进GitHub存储库中的测试之后,我设法创建了一个工作示例。

下面的代码可以解析一个简单的缩进列表:

代码语言:javascript
运行
复制
import Text.Parsec        as Parsec
import Text.Parsec.Indent as Indent

data ExampleList = ExampleList String [ExampleList] 
                 deriving (Eq, Show)

plistItem :: Indent.IndentParser String () String
plistItem = Parsec.many1 Parsec.lower <* Parsec.spaces

pList :: Indent.IndentParser String () ExampleList
pList = Indent.withPos (ExampleList <$> plistItem <*> Parsec.many (Indent.indented *> pList))

useParser :: Indent.IndentParser String () a -> String -> a
useParser p src = helper res
                where res = Indent.runIndent $ Parsec.runParserT (p <* Parsec.eof) () "<test>" src
                      helper (Left err) = error "Parse error"
                      helper (Right ok) = ok

示例用法:

代码语言:javascript
运行
复制
*Main> useParser pList "mylist\n\tfstitem\n\tsnditem"
ExampleList "mylist" [ExampleList "fstitem" [],ExampleList "snditem" []]

请注意,useParser函数做了一些工作,实际获取来自任一单数的结果,以及将文件末尾解析器放在所提供的解析器后面。根据您的应用程序,您可能想要更改此设置。

此外,类型签名可以是这样的缩写:

代码语言:javascript
运行
复制
type IParser a = Indent.IndentParser String () a

plistItem :: IParser String
pList :: IParser ExampleList
useParser :: IParser a -> String -> a
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68130972

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档