【问题标题】:Preserving comments in `Text.Parsec.Token` tokenizers在 `Text.Parsec.Token` 标记器中保留注释
【发布时间】:2014-08-17 09:55:47
【问题描述】:

我正在使用 parsec 编写源到源转换,因此我的语言有一个 LanguageDef,我使用 Text.Parsec.Token.makeTokenParser 为它构建了一个 TokenParser

myLanguage = LanguageDef { ...
  commentStart = "/*"
  , commentEnd = "*/"
  ...
}

-- defines 'stringLiteral', 'identifier', etc...
TokenParser {..} = makeTokenParser myLanguage

不幸的是,因为我定义了commentStartcommentEndTokenParser 中的每个解析器组合器都是根据whiteSpace 实现的词位 解析器,而whiteSpace 吃空格以及 cmets。

在这种情况下保存 cmets 的正确方法是什么?

我能想到的方法:

  1. 不要定义commentStartcommentEnd。将每个词位解析器包装在另一个组合器中,该组合器在解析每个标记之前抓取 cmets。
  2. 实现我自己的makeTokenParser 版本(或者使用一些泛化Text.Parsec.Token 的库;如果是,是哪个库?)

在这种情况下做了什么?

【问题讨论】:

    标签: parsing haskell comments parsec code-translation


    【解决方案1】:

    原则上,定义 commentStart 和 commentEnd 不适合保留 cmets,因为您需要将 cmets 视为源语言和目标语言的有效部分,包括在您的语法和 AST/ADT 中。

    通过这种方式,您可以将评论文本保留为 Comment 构造函数的有效负载数据,并以目标语言适当地输出,类似于

    data Statement = Comment String | Return Expression | ......
    

    源语言和目标语言都不认为评论文本相关这一事实与您的翻译代码无关。


    这种方法的主要问题:它不太适合 makeTokenParser,但更适合从头开始实现源语言的解析器。

    我想我正在转向编辑 makeTokenParser 以让评论解析器返回 String 而不是 ()

    【讨论】:

    • 对,所以我可能应该单独问一个关于用于跟踪 cmets 的最佳 AST 表示的问题。例如,您在此处拥有的那个可能有效(前提是Expression 也有 cmets 的构造函数等...),但另一种方法可能是将 cmets 作为元数据附加到每个 AST 节点(这似乎会更多在 AST 重写操作下健壮)。
    • @Lambdageek 是的,它不会把你的语法弄得一团糟。嗯,是的,某种Either Term (Comment,Term)(Maybe Comment,Term) 在整个树中的转换。哇。这要么真的很丑陋,要么你可以为它做一些非常简洁的免费单子或代数事情。你可以看到为什么默认是把 cmets 扔掉了!
    猜你喜欢
    • 1970-01-01
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多