Я пытался сделать парсер (очень) простой язык, который выглядит следующим образом:Scala комбинаторы синтаксического анализа для (почти) тривиальна грамматика
block{you are a cow too blkA{ but maybe not} and so is he} hear me moo blockZ{moooooo}
Я могу разорвать его на части с помощью регулярных выражений:
.*?[^ ]*?\\{
.*?\\}
, который по существу продолжал бы есть символов, пока не найдет что-то, что соответствует [^ ]*?\\{
или \\}
: начало или конец блока. Мой вопрос: если я хочу это сделать, используя Scars's Parser Combinators, как мне это сделать? Я в настоящее время:
def expr: Parser[Any] = (block | text)+
def text = ".+?".r
def block = "[^ ]*?\\{".r ~ expr ~ "}"
, но это не работает:
parsed: List(b, l, o, c, k, {, y, o, u, a, r, e, a, c, o, w, t, o, o, b, l, k, A, {, b, u, t, m, a, y, b, e, n, o, t, }, a, n, d, s, o, i, s, h, e, }, h, e, a, r, m, e, m, o, o)
кажется, что block
анализатор не стреляя, и поэтому text
парсер увольняют неоднократно. но когда я удалить text
анализатор:
def expr: Parser[Any] = (block)+
я получаю:
failure: string matching regex `[^ ]*?\{' expected but `y' found
block{you are a cow too blkA{ but maybe not} and so is he} hear me moo
^
Так, очевидно, block
анализатор делает работу, за исключением того, не тогда, когда text
анализатор присутствует. Что происходит? и есть ли «правильный» способ сделать это, потому что для такой базовой грамматики?
EDIT: Изменены название, так как это не так много о нежелании больше, как только решая проблему
EDIT: У меня теперь есть это:
def expr: Parser[Any] = (block | text)+
def text = "[^\\}]".r
def block = "[^ ]*?\\{".r ~ expr ~ "}"
Логика в том, что для каждого character, он проверяет, является ли это началом блока. Если это не так, он переходит к следующему символу. Это дает мне:
parsed: List(((block{~List(y, o, u, a, r, e, a, c, o, w, t, o, o, ((blkA{~List(b, u, t, m, a, y, b, e, n, o, t))~}), a, n, d, s, o, i, s, h, e))~}), h, e, a, r, m, e, m, o, o)
который является правильным. Он анализирует неблокированные символы один за другим, хотя это, вероятно, проблема с производительностью (я думаю?). Есть ли способ разобрать все эти неблокированные символы сразу и оставить их в одной большой строке?
Пожалуйста, не добавляйте новые вопросы к существующему. Усильте, конечно, но задавайте новые вопросы по новым вопросам. Он разобирается один за другим, потому что вы использовали неживую звезду. Просто прекратите не жадность. –