如何忽略解析器组合器中的单行注释 [英] How to ignore single line comments in a parser-combinator
问题描述
我有一个可用的解析器,但我刚刚意识到我不适合评论.在我正在解析的 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屋!