2012-02-22 2 views
0

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

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] = "[email protected]" ~> "[^>.]*".r ^^ (new UWAttribute(_)) 

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

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

test0 
[email protected] 
"test2" 
"test3"[email protected] 
test4.. 
[email protected] 
"test6.."[email protected] 
"[email protected]"[email protected] 
test8(urel>uw) 
test9(urel>uw)[email protected] 
"test10..()[email protected]"(urel>uw)[email protected] 
test11(urel1>uw1(urel2>uw2,urel3>uw3),urel4>uw4)[email protected]@attr2 

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

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

Итак, после заголовка МОЖЕТ быть атрибутами и/или модификаторами. Порядок строгий, поэтому атрибуты всегда появляются после модификаторов. Если есть атрибуты, но не модификаторы, все до [email protected] считается частью заглавного слова.

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

ответ

1

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

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

который является первым делом _uw (и, кстати, с помощью подчеркивания в именах в Scala не рекомендуется), поэтому, когда он пытается разобрать [email protected], второе регулярное выражение будет соответствовать всем из этого!

scala> "[^(),]*".r findFirstIn "[email protected]" 
res0: Option[String] = Some([email protected]) 

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

"test6 with a " inside of it.."[email protected] 

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