Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Выражение для парсинга функций

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
BAS-P
Отправлено: 04 Сентября, 2013 - 11:31:29
Post Id


Гость


Покинул форум
Сообщений всего: 74
Дата рег-ции: Июнь 2012  


Помог: 1 раз(а)




Здравствуйте!
Есть задача спарсить php функцию, а тоесть получить её код. Проблема именно в закрывающей }, как точно определить закрывающий тег функции?

Дошел до такого выражения:

CODE (htmlphp):
скопировать код в буфер обмена
  1. "#function ".$methodName."[^{]*{([^}]*)}#"


К примеру если есть файл:

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.  
  3. class test
  4. {
  5.     private function test()
  6.     {
  7.         return 5;
  8.     }
  9.  
  10.     /**
  11.      * Комментарий
  12.      */
  13.     public function NEWMETHOD()
  14.     {
  15.         /**
  16.         * THIS IS NEWMETHOD
  17.         */
  18.         $a = '1';
  19.         if($a == 'b')
  20.         {
  21.             return $a;
  22.         }
  23.  
  24.         /**
  25.          * Ak
  26.          */
  27.  
  28.         return 5;
  29.     }
  30. }
  31.  


То на второй метод оно выдаст

PHP:
скопировать код в буфер обмена
  1.        /**
  2.         * THIS IS NEWMETHOD
  3.         */
  4.         $a = '1';
  5.         if($a == 'b')
  6.         {
  7.             return $a;


Т.е. до первого }, если же убрать [^}]:

CODE (htmlphp):
скопировать код в буфер обмена
  1. "#function ".$methodName."[^{]*{(.*)}#"


То оно естественно выдаст весь код, до конца страницы - до закрывающего тега класса.

Как можно доработать выражение так, чтобы оно доходило до закрывающего тега функции, а тоесть у которого нет перед этим еще открывающего {?

Надеюсь понятно объяснил.
 
 Top
EuGen Администратор
Отправлено: 04 Сентября, 2013 - 11:55:51
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Идея использовать регулярные выражения для этого - плоха. Правильнее - использовать штатные средства, например:
PHP:
скопировать код в буфер обмена
  1. function getBody($sClass, $sMethod, $sFile = __FILE__)
  2. {
  3.     $rMethod = new ReflectionMethod($sClass, $sMethod);
  4.     return trim(join('',array_slice(
  5.             file($sFile),
  6.             $rMethod->getStartLine(),
  7.             $rMethod->getEndLine()-$rMethod->getStartLine()
  8.     )));
  9. }

- тогда это несложно использовать:
PHP:
скопировать код в буфер обмена
  1. class Foo
  2. {
  3.    public function bar()
  4.    {
  5.       return 1;
  6.    }
  7.    
  8.    public function baz()
  9.    {
  10.       if(false)
  11.       {
  12.          exit('1=0');
  13.       }
  14.       return 0;
  15.    }
  16. }
  17. //var_dump(getBody('Foo', 'baz'));

Если файл большой, то использование функций для массивов будет неоптимально (тогда - комбинация while и fgets)


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Мелкий Супермодератор
Отправлено: 04 Сентября, 2013 - 12:00:10
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Регуляркой такое лучше не делать. Потом вспомните, что ещё комментарии есть, которые могут включать всё, что угодно. А ещё есть строки, разрывы ?> и <? и прочие прелести.

Но если очень хочется регуляркой - рекурсивные регулярные выражения. PCRE умеет такое.
Что-то гуглится здесь: http://php.net/manual/ru/regexp....ce.recursive.php , но не читал. Лучше Дж.Фридл "Регулярные выражения" почитать, в 3-ем издании и PHP затронут.


-----
PostgreSQL DBA
 
 Top
BAS-P
Отправлено: 04 Сентября, 2013 - 12:30:11
Post Id


Гость


Покинул форум
Сообщений всего: 74
Дата рег-ции: Июнь 2012  


Помог: 1 раз(а)




Да вот я тут недавно сталкивался с Reflection, но как-то прошел мимо.
А с помощью него можно еще и перезаписывать код метода, или только получать его? Тоесть заменить код на новый и уже перезаписать файл. (а то вижу у него есть только методы get/has/is...)

(Отредактировано автором: 04 Сентября, 2013 - 12:31:16)

 
 Top
caballero
Отправлено: 04 Сентября, 2013 - 12:35:50
Post Id


Активный участник


Покинул форум
Сообщений всего: 5998
Дата рег-ции: Сент. 2011  
Откуда: Харьков


Помог: 126 раз(а)




если получил код метода то перезаписать его можно обычной
str_replace

а вообще фигней занимаетесь. Скажите конкретно зачем вам это надо и вам напишут в чем конкретно эта фигня заключатся.


-----
Бесплатная система складского учета с открытым кодом https://zippy[dot]com[dot]ua/zstore
 
 Top
esterio
Отправлено: 04 Сентября, 2013 - 12:36:40
Post Id



Активный участник


Покинул форум
Сообщений всего: 5025
Дата рег-ции: Нояб. 2012  
Откуда: Украина, Львов


Помог: 127 раз(а)




получит данные с файла до начала функции + сама функция + данные функции после = профит
 
 Top
BAS-P
Отправлено: 04 Сентября, 2013 - 12:48:28
Post Id


Гость


Покинул форум
Сообщений всего: 74
Дата рег-ции: Июнь 2012  


Помог: 1 раз(а)




caballero пишет:
если получил код метода то перезаписать его можно обычной
str_replace


А если я перезаписываю метод test() на примере в первом сообщении, а его код существует и во втором методе? оба заменяются. получается нужно разбивать код на две части: вторая часть начиная с того метода который нужно перезаписать, заменять с str_replace но с дополнением чтобы заменило только один раз, и назад соединять. Или же если регуляркой то preg_replace, но тогда нужна регулярка о которой вопрос в первом сообщении этой темы. Но с регуляркой согласен что проблематично.


caballero пишет:
а вообще фигней занимаетесь. Скажите конкретно зачем вам это надо и вам напишут в чем конкретно эта фигня заключатся.


Я конкретно спрашиваю.

(Отредактировано автором: 04 Сентября, 2013 - 12:56:02)

 
 Top
caballero
Отправлено: 04 Сентября, 2013 - 12:55:40
Post Id


Активный участник


Покинул форум
Сообщений всего: 5998
Дата рег-ции: Сент. 2011  
Откуда: Харьков


Помог: 126 раз(а)




Цитата:
Я конкретно спрашиваю.

я имел ввиду конкретно проблему. на 99% уверен что она решается другими средствами. А оставшийцся один процент не решается никакими регулярками.


-----
Бесплатная система складского учета с открытым кодом https://zippy[dot]com[dot]ua/zstore
 
 Top
EuGen Администратор
Отправлено: 04 Сентября, 2013 - 12:57:38
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




BAS-P
Снова, существуют штатные средства для этой задачи. А именно - расширение RunKit . Reflection не предназначен для таких манипуляций. На деле - если требуется смена кода метода во время исполнения приложения - Вы делаете что-либо не корректно, не существует архитектур, где без этого бы нельзя было обойтись.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
caballero
Отправлено: 04 Сентября, 2013 - 13:03:39
Post Id


Активный участник


Покинул форум
Сообщений всего: 5998
Дата рег-ции: Сент. 2011  
Откуда: Харьков


Помог: 126 раз(а)




EuGen
есть единственная задача когда требуется парсинг кода (кроме самих компиляторов разумеется) - это написание редакторов и всяких плагинов к ним (рефакторинг и иже с ними). Но тут только лексический анализатор и граматика в форме Бекуса-Наура или типа того.


-----
Бесплатная система складского учета с открытым кодом https://zippy[dot]com[dot]ua/zstore
 
 Top
BAS-P
Отправлено: 04 Сентября, 2013 - 13:14:42
Post Id


Гость


Покинул форум
Сообщений всего: 74
Дата рег-ции: Июнь 2012  


Помог: 1 раз(а)




EuGen пишет:
Снова, существуют штатные средства для этой задачи. А именно - расширение RunKit .


Спасибо, правда, он требует специальную конфигурацию (runkit.internal_override)...

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


Суть задачи заключается в следующем: я пробую сделать менеджер страниц на Yii Framework без использования баз данных. То-есть не хочу чтобы страницы хранились в базе данных, а только в самом контроллере и views файлах. Можно конечно использовать CViewAction и тогда для страниц не требуются методы в контроллере (actionPage), но тогда если нужен php код к странице - придется его размещать в самом view-файле, что не есть хорошо. (например страница обратной связи.)
 
 Top
EuGen Администратор
Отправлено: 04 Сентября, 2013 - 13:20:46
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




caballero пишет:
это написание редакторов и всяких плагинов к ним (рефакторинг и иже с ними).

Сомневаюсь, что это потребуется в веб - первое, ну и - как Вы уже заметили - для таких вещей существует РБНФ и прочие соответствующие инструменты - второе. Код анализируется не в терминах методов, а в терминах лексем.
BAS-P пишет:
Суть задачи заключается в следующем

Это должно было быть первым сообщением темы.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
BAS-P
Отправлено: 04 Сентября, 2013 - 14:00:04
Post Id


Гость


Покинул форум
Сообщений всего: 74
Дата рег-ции: Июнь 2012  


Помог: 1 раз(а)




Ну в общем спасибо, попробую с Reflection а насчет редактирования еще подумаю

(Отредактировано автором: 04 Сентября, 2013 - 14:01:01)

 
 Top
Ja_kazanova
Отправлено: 14 Сентября, 2013 - 01:23:27
Post Id



Новичок


Покинул форум
Сообщений всего: 15
Дата рег-ции: Апр. 2013  


Помог: 0 раз(а)




Прочёл только первое сообщение. В голову приходит только посчитать скобки фигурные, разбить на пары их. Ну и если их число не чётное, генерировать ошибку. Именно так я и попытался бы решить эту задачу при надобности.
Чуть не забыл. Отсчет начинать после function.
P.S.
Позвольте поинтересоваться. А зачем Вам это понадобилось?

(Отредактировано автором: 14 Сентября, 2013 - 01:26:12)

 
 Top
BAS-P
Отправлено: 15 Сентября, 2013 - 19:45:35
Post Id


Гость


Покинул форум
Сообщений всего: 74
Дата рег-ции: Июнь 2012  


Помог: 1 раз(а)




Ja_kazanova пишет:
Позвольте поинтересоваться. А зачем Вам это понадобилось?


Чуть выше написано.
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Регулярные выражения »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB