如何忽略解析器组合器中的单行注释 [英] How to ignore single line comments in a parser-combinator

查看:39
本文介绍了如何忽略解析器组合器中的单行注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可用的解析器,但我刚刚意识到我不适合评论.在我正在解析的 DSL 中,注释以 ; 字符开头.如果遇到 ;,该行的 rest 将被忽略(但不是全部,除非第一个字符是 ;).

I have a working parser, but I've just realised I do not cater for comments. In the DSL I am parsing, comments start with a ; character. If a ; is encountered, the rest of the line is ignored (not all of it however, unless the first character is ;).

我正在为我的解析器扩展 RegexParsers 并忽略空格(默认方式),所以无论如何我都会丢失换行符.我也不希望修改每个解析器来满足注释的可能性,因为语句可以跨越多行(因此每个语句的每个部分都可能以注释结尾).有什么干净的方法可以实现吗?

I am extending RegexParsers for my parser and ignoring whitespace (the default way), so I am losing the new line characters anyway. I don't wish to modify each and every parser I have to cater for the possibility of comments either, because statements can span across multiple lines (thus each part of each statement may end with a comment). Is there any clean way to acheive this?

推荐答案

可能影响您选择的一件事是是否可以在您的有效解析器中找到注释.例如,假设您有以下内容:

One thing that may influence your choice is whether comments can be found within your valid parsers. For instance let's say you have something like:

val p = "(" ~> "[a-z]*".r <~ ")"

它会解析类似 ( abc ) 的东西,但由于注释,你实际上可能会遇到类似的东西:

which would parse something like ( abc ) but because of comments you could actually encounter something like:

( ; comment goes here
  abc
)

然后我建议使用 TokenParser 或其子类之一.这是更多的工作,因为您必须提供一个词法解析器,该解析器将执行第一遍以丢弃注释.但是,如果您有嵌套的注释,或者 ; 可以转义,或者 ; 可以在字符串文字中,例如:

Then I would recommend using a TokenParser or one of its subclass. It's more work because you have to provide a lexical parser that will do a first pass to discard the comments. But it is also more flexible if you have nested comments or if the ; can be escaped or if the ; can be inside a string literal like:

abc = "; don't ignore this" ; ignore this

另一方面,您也可以尝试覆盖 空白 类似于

On the other hand, you could also try to override the value of whitespace to be something like

override protected val whiteSpace = """(\s|;.*)+""".r

或者类似的东西.例如使用来自 RegexParsers scaladoc 的示例:

Or something along those lines. For instance using the example from the RegexParsers scaladoc:

import scala.util.parsing.combinator.RegexParsers

object so1 {
  Calculator("""(1 + ; foo
  (1 + 2))
  ; bar""")
}

object Calculator extends RegexParsers {
  override protected val whiteSpace = """(\s|;.*)+""".r
  def number: Parser[Double] = """\d+(\.\d*)?""".r ^^ { _.toDouble }
  def factor: Parser[Double] = number | "(" ~> expr <~ ")"
  def term: Parser[Double] = factor ~ rep("*" ~ factor | "/" ~ factor) ^^ {
    case number ~ list => (number /: list) {
      case (x, "*" ~ y) => x * y
      case (x, "/" ~ y) => x / y
    }
  }
  def expr: Parser[Double] = term ~ rep("+" ~ log(term)("Plus term") | "-" ~ log(term)("Minus term")) ^^ {
    case number ~ list => list.foldLeft(number) { // same as before, using alternate name for /:
      case (x, "+" ~ y) => x + y
      case (x, "-" ~ y) => x - y
    }
  }
  def apply(input: String): Double = parseAll(expr, input) match {
    case Success(result, _) => result
    case failure: NoSuccess => scala.sys.error(failure.msg)
  }
}

打印:

Plus term --> [2.9] parsed: 2.0
Plus term --> [2.10] parsed: 3.0
res0: Double = 4.0

这篇关于如何忽略解析器组合器中的单行注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆