我正在为以下语法编写Scala解析器:
expr := "<" anyString ">" "<" anyString ">"
anyString := // any string
例如,"<foo> <bar>"
是有效字符串,"<http://www.example.com/example> <123>"
和"<1> <_hello>"
到目前为止,我有以下内容:
object MyParser extends JavaTokenParsers {
override def skipWhitespace = false
def expr: Parser[Any] = "<" ~ anyString ~ ">" ~ whiteSpace ~ "<" ~ anyString ~ ">"
def anyString = ???
}
我的问题如下(我已经包含了我的怀疑答案,但无论如何,请确认,如果我是对的!):
如何实现接受任何字符串的正则表达式解析器?这必须有一个几乎无关紧要的答案,如def anyString = """\a*""".r
,其中\a
是代表任何字符的符号(虽然\a
可能不是我正在寻找的机器人。)
如果我将anyString
设置为接受任何字符串,它会在>
符号之前停止,还是会一直运行直到字符串结束并失败?我相信它会一直运行到字符串结束并失败,然后它最终会找到>
并消耗到那里。这似乎导致了一个非常低效的解析器,对此的任何评论都将受到赞赏!
如果<
和>
中的字符串包含>
符号(例如<fo>o> <bar>
),该怎么办? anyString
会消耗到第一个>
还是最后一个?是否有任何方法可以指定它是否能消耗最少,或最多?
为了解决上一点问题,我想在<
中禁止>
anyString
。怎么写呢?。
谢谢!
答案 0 :(得分:1)
我正在研究自己的问题,我会在这里试着回答。
Java Pattern
documentation指定.
匹配任何字符。因此,接受任何字符串的正则表达式将是:
def anyString = ".*".r
要接受任何非空字符串,我们可以使用".+".r
。
要理解这一点,请考虑以下玩具示例:
object MyParser1 {
override def skipWhitespace = false
def expr = "<" ~ anyString ~ ">"
def anyString = ".*".r
}
此处,字符串<>
被拒绝。要测试它,请使用:
println( MyParser1.parseAll(MyParser1.expr, "<>") )
这表示.*
解析器正在消耗,直到字符串结束,因此>
不可用于最终解析器。因此,似乎有必要禁止在<
中出现>
和anyString
表单。
与前一点一样,.*
解析器使用整个字符串,因此会消耗所有>
个符号。
在同一文档中,给出了否定运算符。要排除<
和>
,我们可以写一下:
def almostAnyString = "[^<>]*".r
通常,构造[^abc]
将匹配除 a
,b
和c
之外的任何字符。
总而言之,到目前为止我发现的最佳实现如下:
object MyParser extends JavaTokenParsers {
override def skipWhitespace = false // don't allow whitespace between parsers by default
def expr: Parser[Any] = "<" ~ almostAnyString ~ ">" ~
whiteSpace ~ // this parser is defined in JavaTokenParsers
"<" ~ almostAnyString ~ ">"
def almostAnyString = "[^<>]*".r
}