2014-02-28 3 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, вероятно, не тот дроид, который я ищу).

  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] будет соответствовать любому символу, кроме 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 

} 
+0

Вам не нужно запрещать '<', не так ли? Вопрос в том, нужен ли вам '< c <- d >' для принятия или нет? –

Смежные вопросы