За последние 24 часа нас посетил 21521 программист и 1692 робота. Сейчас ищут 1822 программиста ...

PCRE логика для if/else if

Тема в разделе "Регулярные выражения", создана пользователем TiTanium, 16 июл 2009.

  1. TiTanium

    TiTanium Активный пользователь

    С нами с:
    16 июл 2009
    Сообщения:
    3
    Симпатии:
    0
    Есть свой шаблонизатор все работает отлично, но проблема постоянно возникает с логикой IF/ELSE, причина понятна слабовато знаю PCRE. Я использую вот такое выражение для поиска тегов типа <if name="var">$VAR = TRUE</if>, есть ещё вариант <if name="var">$VAR = TRUE</else>$VAR = FALSE</if>. Сами по себе они работаю, но вот если начитаются вложения типа:
    Код (Text):
    1.  
    2. <if name="var">
    3.   <if name="var2"> </else> </if>
    4. </if>  
    То начинаются и проблемы, при полной жадности он кушает: <if name="var"><if name="var2"> </else> </if> что понятно. вот выражение:
    Код (Text):
    1.  
    2. |<if name="'.$var.'">(.*)</if>|sim
    При ограниченной типа:
    Код (Text):
    1.  
    2. <if name="'.$var.'">(.*?)</if>.|sim
    тоже проблемы нельзя что б за </if> что-то стояло.
    вот еше для if/else:
    Код (Text):
    1.  
    2.   |<if name="'.$var.'">(.*?)</else>(.*?)</if>|sim
    На данный момент решаю проблему парся два раза в зависимости есть ли в квантификаторах: <if name="

    Вот код метода:

    PHP:
    1.  
    2. /**
    3.  *  ПАРСИНГ <if name="">*</if>
    4.  * */
    5. protected function if_($var, $value=false){
    6.   if(!preg_match('|<if name="'.$var.'">(.*?)</if>.|sim', $this->CONTENT, $result) or stristr($result[1],'</else>')){ $result =false; }
    7.  
    8.   if($result and stristr($result[1],'<if name="')){
    9.     if(!preg_match('|<if name="'.$var.'">(.*)</if>.|sim', $this->CONTENT, $result) ){ $result =false; }
    10.   }
    11.   if($result and !empty($result)){
    12.     if($value){  
    13.       $this->put(str_replace($result[0],$result[1],$this->CONTENT));
    14.     }else{
    15.       $this->put(str_replace($result[0],'',$this->CONTENT));   
    16.     }
    17.   }                
    18. }
    19.  
    И даже так частенько происходят накладки с вложениями условиями ((
    Хотелось бы как-то сделать один нормальный PCRE шаблон чтобы отбрасывать такие ситуации. Может кто сталкивался или видел в каком-то шаблонизаторе нормальное выражение.

    Пожалуйста не рекомендуйте свои шаблонизаторы, вопрос состоит не в том какой шаблонизатор выбрать. Приму и не проверенные регулярки сам проверю.
     
  2. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
  3. TiTanium

    TiTanium Активный пользователь

    С нами с:
    16 июл 2009
    Сообщения:
    3
    Симпатии:
    0
    Mr.M.I.T.
    Нет не то, меня интерисует регулярка.
     
  4. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    у тебя принцип неверный
    ты обрабатываешь блоками, а куда проще было бы обрабытвать выражениями
    короче говоря сначала делаешь проверку на синтаксис(нет ли где незакрытых тегов и тд)
    а потом обрабатываешь выражения(<if><esle><elseif></if> и тд)
     
  5. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Вложенность реализовывается наипростейшим образом:

    PHP:
    1. <?
    2.  
    3. $conditions = '<if name="Apple"><div><if age="24">Hi</if></div></if>';
    4.  
    5. /**
    6.  * Реализовываем вложенную логику
    7.  */
    8.  
    9. // Строка с регуляркой
    10. // Мы намеренно используем жадные модификаторы
    11. $pattern = '/<if>(.+)<\/if>/is';
    12.  
    13. while(preg_match($pattern, $conditions)) {
    14.     $conditions = preg_replace($pattern, 'if($name = "Apple") { echo $1; }', $conditions);
    15. }
    16.  
    17. ?>
     
  6. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    Код (Text):
    1. <if name="Apple"><div><if age="24">Hi</if></div><div><if blabla="123">Hi</if></div></if>
    а такое разгребёт?
     
  7. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Неа, он только вложенность разгребает =)
     
  8. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    поменять '/<if(.*?)>(.*?)<\/if>/is' и будет и такое разгребать, как Sergey89 показал и работать быстрее.
     
  9. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Apple
    зло такой подход
     
  10. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Mr.M.I.T., почему ?
     
  11. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    непроизводительный
     
  12. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Mr.M.I.T., спорное утверждение.
    1. У тебя есть факты?
    2. У тебя есть альтернативные решения?
     
  13. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    TheShock, поясни как в этом случае будут вложенные разгребаться?
     
  14. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    хотя да, согласен - тут надо писать кое-что посерьезнее. невнимательно посмотрел.
     
  15. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Пропустив в своём примере вопросительный знак, уменьшающий жадность квантификатора, я не опечатался.
    То, что ты уменьшил жадность, убивает всю ту логику, которую я построил для вложенности.
     
  16. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    С удовольствием посмотрю на другой подход =)
     
  17. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    Сначала выделить все блоки с помощью preg_match. То есть пробегаемся по всему тексту и ищем ифы, потом для каждого ифа ищем ближайший енд, начиная с последнего, чтобы развернуть всё структуру корректно. Ну а дальше уже евалим условие или что-то ещё с ним делаем.
     
  18. TiTanium

    TiTanium Активный пользователь

    С нами с:
    16 июл 2009
    Сообщения:
    3
    Симпатии:
    0
    Есть мнение писать эту логику на конечных автоматах. Но не могу выбрать как бы регулярка будет нагляднее но вот КА будет быстрее, но запутано. Кто бы что предпочол?