Как ограничить нестабильную разметку в комбинаторе Regex и Parser? - PullRequest
0 голосов
/ 04 декабря 2011

Я хотел бы реализовать простой вики-подобный анализатор разметки в качестве упражнения использования комбинатора синтаксического анализатора Scala.

Я бы хотел решить эту проблему постепенно, поэтому вот что я хотел бы достичь в первой версии: простая встроенная литеральная разметка.

Например, если строка ввода:

This is a sytax test ``code here`` . Hello ``World``

Выходная строка должна быть:

This is a sytax test <code>code here</code> . Hello <code>World</code>

Я пытаюсь решить эту проблему с помощью RegexParsers, и вот что я сделал сейчас:

import scala.util.parsing.combinator._
import scala.util.parsing.input._

object TestParser extends RegexParsers
{   
    override val skipWhitespace = false

    def toHTML(s: String) = "<code>" + s.drop(2).dropRight(2) + "</code>"

    val words = """(.)""".r
    val literal = """\B``(.)*``\B""".r ^^ toHTML

    val markup = (literal | words)*

    def run(s: String) = parseAll(markup, s) match {
        case Success(xs, next) => xs.mkString
        case _ => "fail"
    }
}

println (TestParser.run("This is a sytax test ``code here`` . Hello ``World``"))

В этом коде более простой ввод, который содержит только одну <code> разметку, работает нормально, например:

This is a sytax test ``code here``.

стать

This is a sytax test <code>code here</code>.

Но когда я запускаю его с приведенным выше примером, он выдаст

This is a sytax test <code>code here`` . Hello ``World</code>

Я думаю, это потому, что я использую регулярное выражение:

"""\B``(.)*``\B""".r

разрешены любые символы в парах ``.

Я хотел бы знать, должен ли я ограничить число вложенных `` и решить эту проблему?

Ответы [ 3 ]

2 голосов
/ 04 декабря 2011

Вот несколько документов по не жадному сопоставлению:

http://www.exampledepot.com/egs/java.util.regex/Greedy.html

В основном это начинается с первого `` и идет как можно дальше, чтобы получить совпадение, которое соответствует`` в конце света.

Положив?после вашего * вы говорите ему сделать самое короткое совпадение вместо самого длинного совпадения.

Другой вариант - использовать [^ `] * (что угодно, кроме как`), и это заставит его остановиться раньше.

0 голосов
/ 04 декабря 2011

Я не знаю много о парсерах регулярных выражений, но вы можете использовать простой 1-строчный:

def addTags(s: String) =
  """(``.*?``)""".r replaceAllIn (
                    s, m => "<code>" + m.group(0).replace("``", "") + "</code>")

Тест:

scala> addTags("This is a sytax test ``code here`` . Hello ``World``")
res0: String = This is a sytax test <code>code here</code> . Hello <code>World</code>
0 голосов
/ 04 декабря 2011

После некоторых проб и ошибок я обнаружил, что следующее регулярное выражение работает:

"""``(.)*?``"""
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...