从Scala Parser Combinators过滤令牌

时间:2010-07-21 09:17:45

标签: scala parser-combinators

使用Scala解析器组合器时,如何过滤从Lexer到我的Parser的令牌序列?

让我解释一下 - 假设我有一个相当标准的Lexer模式(扩展StdLexical)和一个Parser(扩展StdTokenParsers)。词法分析器将一系列字符转换为一系列标记,然后解析器将标记序列转换为抽象语法树(类型为Expr)。

我决定一些令牌,它们可能出现在流中的任何地方,我想有过滤掉的选项,所以我想要一个适合Lexer和Parser之间移除这些令牌的函数。例如,我可能希望词法分析器标记注释,然后在以后过滤掉这些注释。

编写此过滤器的最佳方法是什么?这可以使用解析器组合器习语,但不必使用。

示例当前代码:

 val reader = new PagedSeqReader(PagedSeq.fromReader(reader))
 val tokens = new MyParser.lexical.Scanner(reader)
 val parse = MyParser.phrase(parser)(tokens)

我希望能够写出这样的内容:

 val reader = new PagedSeqReader(PagedSeq.fromReader(reader))
 val tokens = new MyParser.lexical.Scanner(reader)
 val parse = MyParser.phrase(parser)(filter(tokens))

2 个答案:

答案 0 :(得分:2)

答案 1 :(得分:1)

您是否考虑过使用RegexParsers删除空格和注释?

修改

您可以制作一个简单的过滤器

import scala.util.parsing.input._

object ReaderFilter {
  def filter[T](reader: Reader[T], check: T => Boolean): Reader[T] = {
    new Reader[T] {
      var orig = reader
      def first = { trim; orig.first }
      def atEnd = { trim; orig.atEnd }
      def rest: Reader[T] = { trim; ReaderFilter.filter(orig.rest, check) }
      def pos = orig.pos
      private def trim = {
        while (!orig.atEnd && !check(orig.first))
          orig = orig.rest
      }
    }
  }
}

以这种方式使用它(删除“#”的标记):

val tokens = ReaderFilter.filter(new MyParser.lexical.Scanner(reader), 
          {t:ExprParser.lexical.Token => t.chars != "#"})