Каков наилучший способ захвата неоднозначных сегментов текста?

Как лучше всего захватить внутренний текст в следующем случае?

inner_text = any*;
tag_cdata = '<![CDATA[' inner_text >cdata_start %cdata_end ']]>';

Проблема, кажется, cdata_end действие запускается несколько раз из-за того, что inner_text может совпадать ],

1 ответ

Решение

Я нашел решение. Вы должны справиться с недетерминизмом. Первоначально не было понятно, но правильное решение выглядит примерно так:

inner_text = any*;
tag_cdata = '<![CDATA[' inner_text >text_begin %text_end ']]>' %cdata_end;

action text_begin {
    text_begin_at = p;
}

action text_end {
    text_end_at = p;
}

action cdata_end {
    delegate.cdata(data.byteslice(text_begin_at, text_end_at-text_begin_at))
}

По сути, вы ждете, пока не убедитесь, что проанализировали полный тег CDATA, прежде чем запустить обратный вызов, используя информацию, которую вы ранее перехватили.

Кроме того, я обнаружил, что некоторые формы недетерминизма в Ragel должны быть явно обработаны с использованием приоритетов. Хотя это кажется немного уродливым, в некоторых случаях это единственное решение.

При работе с таким шаблоном, как (a+ >a_begin %a_end | b)* вы обнаружите, что события называются для каждого a встречаются, а не в самой длинной подпоследовательности. Эта неоднозначность, в некоторых случаях, может быть решена, используя самую длинную пару звезд **, Что он делает, так это предпочитает соответствовать существующему шаблону, а не обтеканию.

Что меня удивило, так это то, что это также меняет способ вызова событий. Например, это создает машину, которая не может буферизовать более одного символа за раз при вызове обратных вызовов:

%%{
  machine example;

  action a_begin {}
  action a_end {}

  main := ('a'+ >a_begin %a_end | 'b')*;
}%%

Производит:

Не жадный парсер

Вы заметите, что это вызывает a_begin а также a_end каждый раз.

Напротив, мы можем сделать внутренний цикл и обработку событий жадными:

%%{
  machine example;

  action a_begin {}
  action a_end {}

  main := ('a'+ >a_begin %a_end | 'b')**;
}%%

который производит:

Жадный парсер

Другие вопросы по тегам