【问题标题】:Implementing "includes" when parsing in Attoparsec在 Attoparsec 中解析时实现“包含”
【发布时间】:2019-02-03 10:16:55
【问题描述】:

我写 DSL 是为了好玩。我决定使用 attoparsec,因为我熟悉它。

我想用这样的相对文件名实现包含的解析:

include /some/dir/file.ext

或网址:

include http://blah.com/my/file.ext

因此,当我解析时,我希望读取引用的资源并解析整个事物,将其内容附加到“外部”解析状态。

问题在于,虽然这些语句的解析很容易,但我无法在 Attoparsec 解析器中运行 IO(据我了解)。

如何使用 Attoparsec 来实现这一点?我是否使用一些字符串过滤将初始输入切碎,然后将每个“块”相应地解析为parsefeed?本质上是两遍解析方法?

【问题讨论】:

    标签: parsing haskell attoparsec


    【解决方案1】:

    Attoparsec 是纯的(Data.Attoparsec.Internal.Types.Parser 不是转换器,不包含 IO)所以你是对的,你不能直接从解析器中扩展包含。

    将解析器分成两遍似乎是正确的方法:一遍就像 C 预处理器一样,接受带有include 语句与其他内容交错的文件。 “其他东西”只需要在词法上基本有效,而不是你的完整解析器——就像 C 预处理器只关心标记和匹配括号,不匹配其他括号或任何语义。然后您替换包含,生成一个完全扩展的文件,您可以将其提供给您现有的解析器。

    如果包含的文件在某种意义上必须在语法上是“独立的”,那么您可以先解析整个文件,与includes 交错,然后替换它们。例如:

    -- Whatever items you’re parsing.
    data Item
    
    -- A reference to an included path.
    data Include = Include FilePath
    
    parse :: Parser [Either Include Item]
    
    -- Substitute includes; also calls ‘parse’
    -- recursively until no includes remain.
    substituteIncludes :: [Either Include Item] -> IO [Item]
    

    比如说,如果您只是使用 attoparsec 对无论如何都不能跨越文件边界的令牌进行词法分析,或者您正在执行完整解析但想要禁止包含例如的包含文件不匹配的括号。


    另一种选择是通过使用不同的解析库(例如 megaparsec)将IO 直接嵌入到您的解析器中,它提供了一个ParsecT 转换器,您可以将IO 包裹起来以直接在您的解析器中执行IO .我可能会为原型执行此操作,但将解析和扩展的关注点尽可能分开似乎更整洁。

    【讨论】:

    • 谢谢。我认为我最简单的方法是检查isPrefixOf "import " 的每一行输入,然后根据需要检索和解析。我想我离得不远了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-03
    • 1970-01-01
    相关资源
    最近更新 更多