Я пытаюсь написать парсер для определенного языка как часть моего исследования. В настоящее время у меня проблемы с получением следующего кода для работы так, как я хочу:
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
, но, похоже, ничего не работает. Как взгляд вперед или назад вообще влияет на комбинаторы синтаксического анализа? Я не эксперт по анализу или регулярному выражению, поэтому всякая помощь приветствуется!