рекурсивный поиск в PCRE

romy4

invoke [brain]
рекурсивный поиск в PCRE

Допустим, имеется на входе такая строка
PHP:
$ps="{?plugin=\"foo\" link=\"http://example.com/\" value={?system title?} title=\"go\"?}";
Как видно, в ней есть рекурсивный подвызов {?system title?}. как сделать, чтобы выделить и разобрать все внутренние вхождения (их может быть бесконечное число).

я написал:
PHP:
preg_match("/{(((?>[^{}]+)|(?R))*)}/",$ps,$matches);
Но это работает только с одиночными символами {}, а необходимо, чтобы он ловил {? и ?}.
Я думал сделать (?>[^{}]+) как (?>(?!{\?|\?}).+), но получает ерунда.
 

mymind

Новичок
Я не сталкивался с подобным, но может попробовать по принципу, нашел/заменил. Т.е. сначала ищешь конструкции {? ?} заменяешь их на результат, поставляешь, снва проверяешь на {? ?} и т.д. ... вложений у тебя немного, потому работать будет,думаю, не тормозно.
 

Profic

just Profic (PHP5 BetaTeam)
Где-то так:
~{\?((?:(?>.*?)(?R)*).*)\?}~
но при кривой регулярке рекурсия может быполняться очень долго
 

romy4

invoke [brain]
Profic сейчас пока есть необходимость сделать минимальное... но вот с регулярками у меня пока не выходит, а писать огромный парсер выражений совсем не хочется.
 

ksnk

прохожий
PHP:
$ps="Hello! {?plugin=\"foo\" link=\"http://example.com/\" value={?system {?hello world?} title?} title=\"go\"?} world";
function calculate($s) {
  if (($m=strpos($s,'{?'))!==FALSE)
    return calculate(substr($s,0,$m).calculate(substr($s,$m+2)));
  elseif (($m=strpos($s,'?}'))!==FALSE)
    return calculate(substr($s,0,$m)).substr($s,$m+2);
  else {
    echo $s."\n";
    return "@RESULT@" ;
  }
};
calculate($ps);
Можно, конечно, пооптимизировать, но и так работает на не очень больших строках.

P.S. Теперь лишний раз не вычисляется, хотя и не очень красиво :)
 

romy4

invoke [brain]
ksnk я тоже вчера поколупался и сделал по типу твоей функции. А внутреннее добро уже разбираю регулярками.

-~{}~ 10.02.06 14:57:

хотя вот не знаю, на сколько быстро оно будет работать, потому что ожидается по 2-3 прохода по тексту размером в 60-100 Кб
 

ksnk

прохожий
romy4
Универсальный ответ - проверить :)
Навскидку, для моего алгоритма - каждая открывающая скобка вызывает разбиение строки пополам и анализ половинок. То-есть при начальном размере в 100 кб и глубине рекурсии- 10 получим примерно 1мб. использованной памяти, не считая накладных расходов.
Еще, по моим ощущениям, при работе со строками более 100кб строковые функции начинают ощутимо (непропорционально) притормаживать...

Что понимается под "2-3 прохода"?
 

romy4

invoke [brain]
ksnk у меня немного по-другому. он находит сначала все вложения, отрабатывает их и возвращает ссылку на результат. и так до самого верхнего.

2-3 прохода значит, что код {?...?} может не отрабатыватся при первом проходе, а быть "отложенным" (к примеру, если надо из кода, отработанного в конце, вставить что-то в начало). обычно бывает не более 2х "отложений".
 
Сверху