(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Хак синтаксиса PHP

Источник: habrahabr
olshevskiy87

Вы когда-нибудь задумывались о том, как расширить ядро PHP? Что нужно для того, чтобы создать новое ключевое слово или даже разработать новый синтаксис? Если у вас есть базовые знания языка C, то проблем с созданием небольших изменений возникнуть не должно. Да, я понимаю, что это может быть немного бессмысленно, но неважно - забавно ведь.

Давайте создадим альтернативный способ определения класса. Самый простой способ определения, разрешённый в PHP, выглядит следующим образом:

<?php class ClassName {}
Мы можем упростить синтаксис и заменить фигурные скобки на точку с запятой.

<?php class ClassName;
Если вы попытаетесь выполнить этот код, то он, очевидно, выдаст ошибку. Не проблема, мы можем это исправить.

На первом шаге необходимо установить программное обеспечение.

$ sudo apt-get install bison re2c
PHP написан на C, однако парсер разработан с помощью Bison. Bison - это генератор синтаксических анализаторов. Официальный сайт определяет его, как генератор парсеров общего назначения, который преобразует помеченную контекстно-свободную грамматику в детерминированный LR или обобщенный LR (GLR) анализатор, применяя таблицы LALR-парсера (Look-Ahead LR parser - прим. пер.).

Это очень мощная часть программного обеспечения, о которой можно написать целую книгу. Если захотите узнать больше, я посоветовал бы вам ознакомиться с документацией. Она не из легких, зато содержит хорошие примеры. И если вы когда-нибудь захотите создать язык программирования, то она может стать хорошей стартовой площадкой.

Теперь перейдите на http://php.net и скачайте самые свежие исходники PHP.

$ tar xvjf php-5.4.14.tar.bz2 $ cd php-5.4.14 $ ./configure $ cd Zend $ ls
Снимите шляпу, потому что перед вами ядро PHP. Код в этих файлах управляет подавляющим большинством веб-серверов. Давайте исследуем его.

По умолчанию для файлов генератора Bison используется расширение "y".

$ ls *.y zend_ini_parser.y zend_language_parser.y
Мы не хотим возиться с синтаксисом "ini", поэтому остается только "zend_language_parser.y". Откройте его вашим любимым редактором.

Теперь, если поискать слово "class", то можно обнаружить следующее:

%token T_CLASS "class (T_CLASS)"
Парсер любит работать с токенами. Токен класса - это "T_CLASS". Если вы поищете в тексте "T_CLASS", то найдете нечто подобное:

class_entry_type: T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = 0; } / T_ABSTRACT T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } / T_TRAIT { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_TRAIT; } / T_FINAL T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_FINAL_CLASS; } ;
Перед вами четыре разных способа определения класса.

  1. класс (class)
  2. абстрактный класс (abstract class)
  3. трейт (trait)
  4. финальный (листовой, конечный) класс (final class)

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

Мы на верном пути, но это не совсем то, что мы ищем. Поищите фразу "class_entry_type", которая объединяет те четыре определения класса. Она приведёт вас к пункту назначения. Разобраться в этом легко, но в первый раз читать сложновато.

unticked_class_declaration_statement: class_entry_type T_STRING extends_from { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } implements_list '{' class_statement_list '}' { zend_do_end_class_declaration(&$1, &$3 TSRMLS_CC); } / interface_entry T_STRING { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); } interface_extends_list '{' class_statement_list '}' { zend_do_end_class_declaration(&$1, NULL TSRMLS_CC); } ;
Здесь есть два объявления. Одно для класса, другое для интерфейса. Нас интересует первое. Оно начинается с "class_entry_type", которое разрешает конструкции: class / abstract class / trait / final class. Следующий элемент - это токен T_STRING. В будущем на его месте будет имя класса. "extends_from" - это группа. Этот элемент может быть преобразован в "extends T_STRING" или оставаться пустым.

После этого парсер вызывает движок Zend, чтобы начать объявление класса.

{ zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); }
Вы можете найти эту функцию в файле  zend_compiler.c .

void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC)
Первый аргумент здесь - это токен класса "class_entry_type", второй - имя класса "T_STRING", а последний - родительский класс "extends_from".

Ниже идёт группа "implements_list". Уверен, что вы знаете, зачем она нужна. Верно, для определения интерфейсов. Следующие строки образуют обязательное тело класса: открывающая фигурная скобка "{", группа "class_statement_list" и закрывающая фигурная скобка "}". Наконец, парсер сообщает движку Zend, что объявление класса окончено.

{ zend_do_end_class_declaration(&$1, &$3 TSRMLS_CC); }
Нам необходимо продублировать этот код, но уже без тела класса.

unticked_class_declaration_statement: class_entry_type T_STRING extends_from { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } ';' { zend_do_end_class_declaration(&$1, &$3 TSRMLS_CC); } / class_entry_type T_STRING extends_from { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } implements_list '{' class_statement_list '}' { zend_do_end_class_declaration(&$1, &$3 TSRMLS_CC); } / interface_entry T_STRING { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); } interface_extends_list '{' class_statement_list '}' { zend_do_end_class_declaration(&$1, NULL TSRMLS_CC); } ;
Это было довольно просто, не так ли? Теперь вам остаётся лишь скомпилировать изменения.

$ cd .. $ make
Первая компиляция всегда занимает некоторое время.

$ vim test.php
Введите код для тестирования.

<?php class FooBar; $a = new FooBar; $a->bar = 10; print_r($a);
А теперь протестируйте его.

$ sapi/cli/php test.php FooBar Object ( [bar] => 10 )
Отлично, у вас получилось!

Давайте сделаем еще кое-что. В PHP вы объявляете класс с помощью ключевого слова "class". Как насчет того, чтобы сделать его покороче? Думаю, "cls", подойдёт.

Ищем файлы лексера:

$ cd Zend/ $ ls *.l zend_ini_scanner.l zend_language_scanner.l
Файл Bison оперировал токенами. Лексер позволяет вам решать как преобразовывать код в токены. Откройте zend_language_scanner.l и поищите слово "class".

<ST_IN_SCRIPTING>"class" { return T_CLASS; }
Продублируйте этот блок и измените class на cls.

<ST_IN_SCRIPTING>"cls" { return T_CLASS; } <ST_IN_SCRIPTING>"class" { return T_CLASS; }
Дело сделано. Скомпилируйте код и можете использовать ключевое слово "cls" вместо "class".

Не правда ли забавно? Надеюсь, вам было приятно также, как и мне. Интересуйтесь, исследуйте.

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 21.05.2013 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
erwin Data Modeler Navigator Edition r9.7 - Product plus 1 Year Enterprise Maintenance Commercial
Allround Automation Direct Oracle Access Standard license
Kerio Connect - Server (incl 5 users, 1 yr SWM)
Kaspersky Internet Security для всех устройств. 3-Device 1 year Base Download Pack
ABBYY FineReader 14 Standard Full
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Безопасность компьютерных сетей и защита информации
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
СУБД Oracle "с нуля"
OS Linux для начинающих. Новости + статьи + обзоры + ссылки
Компьютерные книги. Рецензии и отзывы
Утиль - лучший бесплатный софт для Windows
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
Обсуждения в форумах
Специалист по reverse engineering (2)
Предлагаю услуги по реверсу и модификации различных программ.
 
Пишу программы на заказ профессионально (2242)
Пишу программы на заказ на языках Pascal (численные методы, списки, деревья, прерывания) под...
 
Помощь по MS Access (327)
Доброе время суток. Случайно оказался на этом сайте, искал статьи по OLAP. Вижу, что...
 
Ищу программиста для написания программы (16)
Ищу программиста ,владеющего Вижуал Бэйсик и программированием в Экселе, для написания...
 
Hiwork.ru - новая интернет-площадка для поиска работы и размещения вакансий (1)
Всем привет! Команда HiWork приглашает работодателей и соискателей на новый интернет-ресурс...
 
 
 



    
rambler's top100 Rambler's Top100