Простой пример Ragel, который уравновешивает скобки?

Вот отправная точка для грамматики:

%%{
  machine xo;

  char = "x" | "o";
  group = "(" char* ")";
  main := group;
}%%

Например, он обрабатывает (xxxx(oo)()xx). Как мне расширить его, чтобы разрешить вложенные группы; например. (xxxx(o(x)o)()xx?

Я знаю, что рекурсия, как правило, не поддерживается одной машиной Ragel. Так что это не сработает:

group = "(" ( char | group )* ")";

Из Руководство пользователя компилятора конечного автомата Ragel (PDF):(жирный текст добавлен для выделения):

"In general Ragel cannot handle recursive structures because the grammar is interpreted as a regular language. However, depending on what needs to be parsed it is sometimes practical to implement the recursive parts using manual coding techniques. This often works in cases where the recursive structures are simple and easy to recognize, such as in the balancing of parentheses."

"One approach to parsing recursive structures is to use actions that increment and decrement counters or otherwise recognize the entry to and exit from recursive structures and then jump to the appropriate machine defnition using fcall and fret. Alternatively, semantic conditions can be used to test counter variables.

"A more traditional approach is to call a separate parsing function (expressed in the host lan- guage) when a recursive structure is entered, then later return when the end is recognized."

Из обсуждения списка рассылки по вложенным скобкам упоминаются те же три подхода :

  1. Specify a growable stack using prepush and postpop and then use fcall and fret.

  2. Counting and then verify in actions or conditions.

  3. Call a new parsing function (in the host language) when the recursive structure is entered.

. Можете ли вы указать мне пример каждого --, предпочтительно используя мой пример выше --в Ruby? Спасибо!

7
задан LinuxDev 14 February 2018 в 13:56
поделиться