2014-02-28 19 views
0

我正在写一个解析器的Scala为以下语法:解析器接受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 = ??? 

} 

我的问题如下(我已经包括了我的疑似答案,但无论如何请确认,如果我没错的话):

  1. 如何实现接受任何字符串的正则表达式解析器?这必须有一个几乎微不足道的答案,如def anyString = """\a*""".r,其中\a是代表任何字符的符号(尽管\a可能不是我正在寻找的droid)。

  2. 如果我设置anyString接受任何字符串,它会在>符号之前停止,还是会运行直到字符串结束并失败?我相信它会一直运行直到字符串结束并失败,然后它最终会找到>并消耗到那里。这似乎导致非常低效的解析器,并且对此的任何评论将不胜感激!

  3. 如果有什么内<>字符串中包含>符号(例如<fo>o> <bar>)?将anyString消耗到第一个>还是最后一个?有没有什么方法可以指定它是否消耗最少或最多?

  4. 为了解决上述问题,我想禁止<>anyString。如何写这个?

谢谢!

回答

0

我目前正在研究自己的问题,我会尽力在这里回答我自己。

  1. Java的Patterndocumentation指定.任何字符匹配。因此,它接受任何字符串正则表达式是:

    def anyString = ".*".r 
    

    接受任何非空字符串,我们可以使用".+".r

  2. 要理解这一点,考虑下面的玩具例子:

    object MyParser1 { 
        override def skipWhitespace = false 
        def expr = "<" ~ anyString ~ ">" 
        def anyString = ".*".r 
    } 
    

    这里,串<>拒绝。为了测试这一点,使用:

    println( MyParser1.parseAll(MyParser1.expr, "<>") ) 
    

    这表明.*解析器消耗直到串,由此>不适用于最终的解析器的端部。因此,似乎有必要禁止在anyString中出现<>表单。

  3. 如前面一点,.*解析器消耗整个字符串,因此消耗所有>符号。

  4. 在同一文档中给出否定运算符。为了排除<>,我们可以这样写:

    def almostAnyString = "[^<>]*".r 
    

    一般来说,结构[^abc]将任何字符匹配除了abc

总之,到目前为止,我已经找到了最好的实现如下:

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 

} 
+0

你并不真的需要禁止'<',你呢?问题是,你需要'< c <- d >'被接受吗? –