【问题标题】:Extending input in Haskell Parsec在 Haskell Parsec 中扩展输入
【发布时间】:2023-04-03 09:16:01
【问题描述】:

我想为一种允许文件包含的简单语言实现 Parsec 解析器。即,语言如下所示:

include otherfile;

expression in the language;

如果一个包含被解析,我想读取一个具有此名称的文件并将其解析的内容嵌入到父结构中。

由于我要读取一个文件,所以解析器需要打包在 IO 中。我的猜测是 ParsecT s u m a 中的 underyling monad u 可以用于此目的。但是,这会导致语言定义发生相当大的变化,因为 LanguageDef 依赖于 Identity 作为底层单子。

我的方法合理吗?是否有其他方法可以在解析器中包含文件,例如扩展输入流?

【问题讨论】:

  • 如果otherfile 链接回当前文件以致出现include 循环怎么办。
  • otherfile 位于子目录中,不能包含当前文件(该语言不是正确的编程语言,而是一种培训语言)。不能发生循环引用。
  • 你能处理标记器中的“包含”吗?或者称它为“#include”并在解析之前通过“cpp”传递文件?
  • 你是对的,这似乎也是一种合理的方法。我将看到将分词器拆开有多复杂。
  • Parsec 等人不允许您动态更改输入流,afaik。我看到了一些合理的方法来做到这一点。一种是使用预处理器(cpp 或定制的)对输入进行文本替换。另一种方法是在您的 AST 中包含include 的案例,直接解析文件,然后将 AST 重写为单独的编译过程。第三个是在IO 之上构建解析器,加载并解析包含的文件,然后将返回的树附加到解析器本身中。

标签: parsing haskell io parsec


【解决方案1】:

好的,这就是我想出的:

parsecTrans :: Monad m => ParsecT s u Identity a -> ParsecT s u m a
parsecTrans p = mkPT $ \s -> return $ fmap (return . runIdentity) $ runIdentity $ (runParsecT p) s

此函数解包ParsecT monad 并将其推广到任意monad。您可以使用它将所有基于Identity 的解析器提升为基于IO 的解析器。

【讨论】:

  • 我可能会为ParsecT s u 写一个MFunctor 的实例并写parsecTrans = hoist generalize
猜你喜欢
  • 2017-07-24
  • 1970-01-01
  • 1970-01-01
  • 2013-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多