Scala парсер комбинаторы: как разобрать "if (x)" если x может содержать ") - PullRequest
1 голос
/ 24 мая 2010

Я пытаюсь заставить это работать:

def emptyCond: Parser[Cond] = ("if" ~ "(") ~> regularStr <~ ")" ^^ { case s => Cond("",Nil,Nil) }

, где normalStr определено для принятия нескольких вещей, включая ")". Конечно, я хочу, чтобы это был приемлемый ввод: if (foo ()) . Но для любого if (x) он принимает символ ")" как часть normalStr , и поэтому этот синтаксический анализатор никогда не завершается успешно.

Чего мне не хватает?

Редактировать

normalStr не является регулярным выражением. Определяется так:

  def regularStr = rep(ident | numericLit | decimalLit | stringLit | stmtSymbol) ^^ { case s => s.mkString(" ") }

и символы:

  val stmtSymbol = "*" | "&" | "." | "::" | "(" | ")" | "*" | ">=" | "<=" | "=" | 
               "<" | ">" | "|" | "-" | "," | "^" | "[" | "]" | "?" | ":" | "+" |
               "-=" | "+=" | "*=" | "/=" | "&&" | "||" | "&=" | "|="

Мне не нужна исчерпывающая проверка языка, только структуры управления. Так что мне все равно, что внутри "()" в if (), я хочу принять любую последовательность идентификаторов, символов и т. Д. Поэтому для моих целей даже if ())) должно быть допустимо, где "))" - это условие if.

Ответы [ 2 ]

6 голосов
/ 24 мая 2010

Регулярное выражение не может распознать язык с вложенными сбалансированными конструкциями, такими как (...), [...], {...} и т. Д. Таким образом, вам понадобится использовать дополнительные контекстно-свободные произведения (не регулярные выражения)), чтобы соответствовать regularStr порциям.

0 голосов
/ 26 мая 2010

ОК, принятие if ())) на самом деле не было требованием, это просто пример того, что я хотел бы принять, чтобы сделать мой анализ как можно более дешевым, чтобы просто беспокоиться о захвате управляющих структур.

Однако, похоже, я не могу быть таким дешевым, и все же у меня это работает. Итак, поскольку конструкция if () содержит круглые скобки, все, что мне нужно сделать, - это ожидать, чтобы внутри было хорошо сбалансированные скобки. Закрытие ")", где никто не ожидается, не может быть частью условия.

Я сделал это:

  val regularNoParens = ident | numericLit | decimalLit | stringLit | stmtSymbol 
  def regularParens: Parser[String] = "(" ~ rep(regularNoParens | regularParens) ~ ")" ^^ { case l ~ s ~ r => l + s.mkString(" ") + r } 
  def regularStr = rep(regularNoParens | regularParens) ^^ { case s => s.mkString(" ") }

И я вынул "(" и ")" из stmtSymbol. Работает!

Редактировать: он не поддерживал вложение, исправил его.

...