Переполнение стека, которое вы испытываете, возможно, является результатом леворекурсивного языка:
def combinedPredicate = predicate ~ ...
def predicate = combinedPrediacate | ...
Комбинаторы парсеров в Scala 2.7 являются парсерами рекурсивного спуска. У парсеров рекурсивного спуска есть проблемы с ними, потому что они понятия не имеют, каков символ терминала, когда они впервые сталкиваются с ним. Другие виды синтаксических анализаторов, такие как пакетные парсин-комбинаторы Scala 2.8, не будут иметь проблем с этим, хотя вам нужно определить грамматику, используя lazy val
s вместо методов, например:
lazy val combinedPredicate = predicate ~ ...
lazy val predicate = combinedPrediacate | ...
Кроме того, вы можете изменить язык, чтобы избежать левой рекурсии. Исходя из приведенного вами примера, требование наличия скобок на этом языке может эффективно решить проблему.
def combinedPredicate = predicate ~ ...
def predicate = "(" ~> combinedPrediacate <~ ")" | ...
Теперь каждый более глубокий уровень рекурсии соответствует другим проанализированным скобкам. Вы знаете, что вам не нужно возвращаться глубже, когда у вас заканчиваются скобки.