2016-11-19 6 views
1

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

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

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

ответ

2

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

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, а не в самой длинной подпоследовательности. Эта двусмысленность, в некоторых случаях, может быть решена с использованием самого длинного матча kleene star **. Что это значит, он предпочитает сопоставлять существующий шаблон, а не обертывать.

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

%%{ 
    machine example; 

    action a_begin {} 
    action a_end {} 

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

Производит:

Non-greedy Parser

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

В отличие от этого, мы можем сделать внутренний цикл и обработка событий жадные:

%%{ 
    machine example; 

    action a_begin {} 
    action a_end {} 

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

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

Greedy Parser

+0

Разве это не странно, когда вы нашли собственное решение в год будущее и думаю, я действительно написал это !? :) – ioquatix