Невозможно проанализировать сложный язык с помощью регулярных выражений и комбинаторов синтаксического анализа Scala - PullRequest
0 голосов
/ 22 февраля 2012

Я пытаюсь написать парсер для определенного языка как часть моего исследования. В настоящее время у меня проблемы с получением следующего кода для работы так, как я хочу:

private def _uw: Parser[UW] = _headword ~ _modifiers ~ _attributes ^^ {
  case hw ~ mods ~ attrs => new UW(hw, mods, attrs)
}

private def _headword[String] = "\".*\"".r | "[^(),]*".r

private def _modifiers: Parser[List[UWModifier]] = opt("(" ~> repsep(_modifier, ",") <~ ")") ^^ {
  case Some(mods) => mods
  case None       => List[UWModifier]()
}

private def _modifier: Parser[UWModifier] = ("[^><]*".r ^^ (RelTypes.toRelType(_))) ~ "[><]".r ~ _uw ^^ {
  case (rel: RelType) ~ x ~ (uw: UW) => new UWModifier(rel, uw)
}

private def _attributes: Parser[List[UWAttribute]] = rep(_attribute) ^^ {
  case Nil   => List[UWAttribute]()
  case attrs => attrs
}

private def _attribute: Parser[UWAttribute] = ".@" ~> "[^>.]*".r ^^ (new UWAttribute(_))

Приведенный выше код содержит только одну часть языка, и чтобы сэкономить время и пространство, я не буду вдаваться в подробности о языке в целом. Предполагается, что метод _uw анализирует строку, состоящую из трех частей, хотя в строке должна существовать только первая часть.

_uw должен уметь правильно анализировать эти тестовые строки:

test0
test1.@attr
"test2"
"test3".@attr
test4..
test5..@attr
"test6..".@attr
"test7.@attr".@attr
test8(urel>uw)
test9(urel>uw).@attr
"test10..().@"(urel>uw).@attr
test11(urel1>uw1(urel2>uw2,urel3>uw3),urel4>uw4).@attr1.@attr2

Таким образом, если заглавное слово начинается и заканчивается ", все, что находится в двойных кавычках, считается частью заглавного слова. Все слова, начинающиеся с .@, если они не находятся в двойных кавычках, являются атрибутами заголовка.

например. в test5 синтаксический анализатор должен анализировать test5. как ключевое слово и attr как атрибут. Просто. @ Опущено, и все точки перед этим должны быть включены в ключевое слово.

Таким образом, после заголовка МОГУТ быть атрибуты и / или модификаторы. Порядок строг, поэтому атрибуты всегда идут после модификаторов. Если есть атрибуты, но нет модификаторов, все до .@ считается частью заголовка.

Основная проблема "[^@(]*".r. Я пробовал все виды творческих альтернатив, таких как "(^[\\w\\.]*)((\\.\\@)|$)".r, но, похоже, ничего не работает. Как взгляд вперед или назад вообще влияет на комбинаторы синтаксического анализа? Я не эксперт по анализу или регулярному выражению, поэтому всякая помощь приветствуется!

1 Ответ

1 голос
/ 23 февраля 2012

Я не думаю, что "[^@(]*".r имеет какое-либо отношение к вашей проблеме.Я вижу это:

private def _headword[String] = "\".*\"".r | "[^(),]*".r

, что является первым в _uw (и, кстати, использование подчеркивания в именах в Scala не рекомендуется), поэтому, когда он пытается проанализировать test5..@attr,второе регулярное выражение будет соответствовать всему этому!

scala> "[^(),]*".r findFirstIn "test5..@attr"
res0: Option[String] = Some(test5..@attr)

Таким образом, для оставшихся парсеров ничего не останется.Кроме того, первое регулярное выражение в _headword также проблематично, потому что .* будет принимать кавычки, что означает, что что-то подобное становится действительным:

"test6 with a " inside of it..".@attr

Что касается просмотра вперед и назад, то этоне влияет на комбинаторы парсеров вообще.Либо регулярное выражение соответствует, либо нет - это все, что волнует комбинатор синтаксического анализатора.

...