Pull to refresh

Модуль HTML::Phl для обработки HTML-документов, содержащих инструкции с кодом Perl

Reading time21 min
Views2.8K


В статье приведена спецификация модуля HTML::Phl для работы с HTML-документами, содержащими код языка программирования Perl.

Задача модуля HTML::Phl — выбрать из текстового документа формата HTML, размещенный в нем особым образом perl-код, выполнить кое-какие манипуляции над ним и остальным кодом, объединить полученное в единый код perl и «скормить» всё это 'eval', получая на выходе сгенерированную HTML-страницу, воспроизводимую веб-браузером.

Пример
1   <HTML>
2   <HEAD>
3   <META content="text/html; charset=UTF-8" http-equiv="Content-Type">
4   <TITLE>Пример PHL</TITLE>
5   </HEAD>
6   
7   Создаем два дочерних процесса f1 и f2<br>
8
9   %pl  include("process_win.phl", "fork decode=cp1251", "f1");
10  %pl  include("process_utf.phl", "fork decode=utf8", "f2");
11
12  Ждем завершения процессов<br>
13
14  <%pl my %join = include("JOIN", "f1 f2"); %>
15
16  Результаты выполнения процессов<br>
17
18  <%pl
19     foreach my $key(keys(%join)) {
20        if (ref $join{$key}) {
21           print "процесс '$key' - результат: ";
22           for (my $i = 0; $i <= $#{$join{$key}}; $i++) {
23              print "'${$join{$key}}[$i]' ";
24           }
25           print "<br>";
26        } else {
27           print "процесс '$key' - результат: '$join{$key}'<br>";
28        }
29     }
30  %>
31   
32  </HTML>


Статья написана в ознакомительных целях, разработка модуля носит концептуальный характер, и его надежное применение нуждается в дополнительном тестировании.



Оглавление:


Спецификация PHL
Указатели
Разделители
Ключи
Функции
Модули-расширения
Конфигурационные настройки
Дистрибутив PHL


Спецификация PHL  ^ 


В HTML документе perl-код размещается с помощью своеобразных инструкций. У каждой такой инструкции есть начало и конец, позволяющие идентифицировать код perl в документе.
В спецификации PHL определено три варианта написания инструкций:

1. Линейная инструкция:

   %pl [keys] [perl code]

2. Инструкция в виде однострочного блока:

   <%pl[(:|=)[name]] [keys] [perl code] %>

3. Многострочный блок:

   <%pl[(:|=)[name]] [keys]
  [perl code]

   %>

где

'%pl', '<%pl', '%>' — указатели инструкции (определяют начало и конец кода Perl);

[name] — имя блока (используется при идентификации блоков, преимущественно при параллельном программировании);

':' или '=' — разделители (с одной стороны являются разделителями между указателями инструкции и именем блока, с другой стороны, обладают рядом дополнительных функциональных особенностей);

[keys] — управляющие ключи (позволяют видоизменять код Perl, заключенный в инструкции, перед тем как его передать интерпретатору на выполнение);

[perl code] — код Perl.

Примеры
  %pl print sqrt(2);

  <%pl print $var; %>
  
  <%pl= $var; %>
  
  <%pl
      foreach my $key(keys(%ENV)) {
         print "$key — $ENV{$key}<br>";
      }
  %>


Управляющие элементы [name] и [keys] используются не так часто, и с успехом можно обойтись и без них, но их использование бывает весьма удобным.

  <%pl:f1 -fork
     # Код дочернего процесса
     my $f = "Данные дочернего процесса f1";
     sleep 1;
     return $f;
  %>
  
  <%pl -join=f1
     # Результат дочернего процесса f1
     print $phl_join{f1};
  %>

К стандартным функциям Perl в PHL дополнительно добавлена функция 'include()'), реализованная для возможности сборки документа из нескольких файлов.

  %pl include($file_name);
     
  <%pl include("$file_name", "socket"); %>

  <%pl
     my $result = include("$file_name", "open decode");
  %>


Указатели  ^ 


По умолчанию указатели имеют вид: '<%pl', '%>' и '%pl'.

Указатели можно переопределить в настройках файла 'Phl.pm' или в конфигурационном файле 'config.phl'. В результате, можно написать так <% ...code perl… %> или так [ ...code perl… ] или даже вoт так ¦ ...code perl… ¦.

При желании можно определить свои собственные (дополнительные) указатели инструкций. Это реализуется с помощью специально оформленных модулей.

К примеру, с помощью модуля 'HTML::Phl::Php' в дополнение к указателю инструкции '<%pl' добавляется указатель '<%php', позволяющий выполнить простой код языка программирования PHP.

 1  %pl -ev use HTML::Phl::Php;
 2  
 3  <%php
 4    echo "PHP >> <b>OK</b><br>";
 5    echo date('H:i:s d.m.Y');
 6  %>

Результат
PHP >> OK
14:23:22 26.12.2016


Разделители ^ 


Задача разделителей — отделить указатель инструкции от имени блока.

В отличие от разделителя ':', разделитель '=' изменяет в анализаторе интерпретацию кода. При этом, результат применения разделителя '=' в однострочном и многострочном блоках различаются.

 1  %pl  my $test = "<b>тест</b>";
 2  
 3  1. Переменная '<%pl= $test %>' внутри однострочного блока.
 4  <br><br>
 5  
 6  <%pl=name1
 7     2. Переменная '$test' внутри
 8     многострочного блока '<b>$phl_blok[1]</b>' (разделитель '=').
 9  %>
 10  <br><br>
 11  
 12  <%pl:name2
 13     print "3. Переменная '$test'";
 14     print "внутри многострочного блока '<b>$phl_blok[2]</b>' (разделитель ':').";
 15  %>

Код после анализатора
 1  my $test = "<b>тест</b>";
 2  print <<'[HTML]';
 3   
 4  [HTML]
 5  print <<'[HTML]' =~ /(.*)/;
 6  1. Переменная '
 7  [HTML]
 8  print($test);
 9  print <<'[HTML]';
 10  ' внутри однострочного блока.
 11  [HTML]
 12  print <<'[HTML]';
 13  <br><br>
 14   
 15  [HTML]
 16  print <<"[HTML]";
 17     2. Переменная "$test" внутри
 18     многострочного блока "<b>$phl_blok[1]</b>" (разделитель "=").
 19  [HTML]
 20  print <<'[HTML]';
 21  <br><br>
 22   
 23  [HTML]
 24     print "3. Переменная '$test'";
 25     print "внутри многострочного блока '<b>$phl_blok[2]</b>' (разделитель ':').";


Результат
1. Переменная 'тест' внутри однострочного блока.

2. Переменная 'тест' внутри многострочного блока 'name1' (разделитель '=').

3. Переменная 'тест'внутри многострочного блока 'name2' (разделитель ':').


Ключи ^ 


Ключи позволяют видоизменять код perl, размещенный в инструкциях. Их можно указывать в полном или в сокращенном виде:

-begin
-end
-perl_all
-eval
-fork
-thread
-join

• Ключи '-begin' [ '-bg' ] и '-end'


При использовании ключа '-begin' анализатор берет код perl, содержащийся в инструкции, и оборачивает его блоком 'BEGIN {}'.

То же самое происходит при использовании ключа '-end' — код perl помещается в блок 'END {}'.

Исходный код:

 1  1. Текст HTML<br>
 2  <%pl -end
 3     print "2. Первый end<br>";
 4  %>
 5  3. Текст HTML<br>
 6  
 7  <%pl -begin
 8     print "4. Первый begin<br>";
 9  %>
 10 5. Текст HTML<br>
 11  
 12 <%pl -end
 13    print "6. Второй end<br>";
 14 %>
 15 7. Текст HTML<br>
 16  
 17 <%pl -bg
 18    print "8. Второй begin<br>";
 19 %>
 20 9. Текст HTML<br>

Результат
4. Первый begin
8. Второй begin
1. Текст HTML
3. Текст HTML
5. Текст HTML
7. Текст HTML
9. Текст HTML
6. Второй end
2. Первый end

• Ключ '-perl_all' [ '-pl' ]


При использовании данного ключа, отпадает необходимость ограничивать код perl указателями инструкций. Анализатор будет воспринимать весь текст документа, как Perl-код.

 1  %pl -pl
 2  
 3  use CGI;
 4  
 5  print "Content-type: text/html; charset=utf-8\n\n";
 6  
 7  my $test = "Текст";
 8  my $q = new CGI;
 9  
 10  print $q -> h4("$test из модуля CGI");
 11  print ("<H4>$test из Phl</H4>");

Результат

Текст из модуля CGI


Текст из Phl



• Ключ '-eval' [ '-ev' ]


Ключ позволяет выполнить код, заключенный внутри инструкции, в процессе работы анализатора (перед его выполнением eval).

Например, попробуем с помощью данного ключа изменить указатели '&lt%pl' и др., разместив в коде следующую инструкцию:

 1  <%pl -eval
 2    $phl{lt} = '[';
 3    $phl{rt} = ']';
 4    $phl{ln} = '~';
 5    $phl{sh} = '';
 6  %>

Указатели инструкций приобрели совершенно другой вид. Теперь инструкцию можно написать таким вот образом:

 1  [=
 2    Многострочный блок
 3  ]

или таким

 1  [ print "Однострочный блок" ]

или таким

 1  ~ print "Линейная инструкция"

• Ключ '-fork' [ '-fk' ]


Код, заключенный внутри инструкции, выполняется в параллельном дочернем процессе, созданном в результате запуска fork().

 1  <%pl:f1 -fork
 2    # Код дочернего процесса с именем f1
 3    my $f;
 4    sleep 1; # Параллельная обработка данных процессом f1
 5    return $f;
 6  %>

• Ключ '-thread' [ '-td' ]


Код, заключенный внутри инструкции, выполняется в параллельном потоке («нити», «ветке» процесса), созданном стандартным модулем 'threads' в рамках одного процесса.

 1  <%pl:t1 -thread
 2    # Код нити с именем t1
 3    my $t;
 4    sleep 1; # Параллельная обработка данных нитью t1
 5    return $t;
 6  %>

• Ключ '-join' [ '-jn' ]


Ключ дает возможность получить результаты выполнения дочерних процессов и нитей.

Результаты размещаются в хэше %phl_join, ключами которого являются имена создаваемых процессов/потоков. Если при обращении за результатом нужные параллельные процессы ещё не завершились, программа ждет их завершения.

 1  <%pl -join
 2    # Результаты выполнения параллельных дочерних процессов и потоков
 3    foreach my $key(keys(%phl_join)) {
 4        if (ref $phl_join{$key}) {  # если значение - ссылка
 5          my @result = @{$phl_join{$key}};
 6          print "процесс '$key' - результат первого аргумента '$result[0]'";
 7        } else {
 8          print "процесс '$key' - результат '$phl_join{$key}'";
 9        }
 10    }
 11  %>

• Дополнительные ключи


При желании можно определить свои собственные (дополнительные) ключи или переопределить существующие. Это реализуется с помощью специально оформленных модулей.

Так, к примеру, с помощью модуля 'HTML::Phl::Utilit' и ключа '-import' [ '-im' ] можно просмотреть список всех указателей, ключей и параметров, в данный момент доступных программе.

 1  %pl -ev use HTML::Phl::Utilit;
 2  
 3  %pl -import

Результат
1. HTML::Phl::Php
    • param:
        — php
    • sh:
        — php
2. HTML::Phl::Psimple
    • param:
        — Simple
        — sl
3. HTML::Phl::Result
    • param:
        — result
4. HTML::Phl::Ru
    • sh:
        — рус
5. HTML::Phl::Utilit
    • eval:
        — analys
        — as
        — listing
        — lt
    • include:
        — CONFIG
        — TIMER
    • key:
        — analys
        — as
        — cf
        — config
        — im
        — import
        — listing
        — lt
        — no_timer
        — nt
        — timer
        — tm
    • param:
        — listing
        — lt


Функции ^ 


В PHL добавлена всего одна функция 'include()', реализованная для возможности сборки документа из нескольких файлов, содержащих HTML (TXT) или PHL разметку.

Функция 'include()' похожа на стандартную Perl функцию 'open()', с тем отличием, что первым аргументом является имя включаемого в документ файла, а вторым — один или несколько специальных управляющих параметров.

 1  %pl include($file_name);
 2     
 3  <%pl include("$file_name", "socket"); %>
 4  
 5  <%pl
 6     my $result = include($file_name, "open decode");
 7  %>

В общем случае, написание функции 'include()' выглядит так:

include("file_name" [, "param" [, "name_process"]]);

file_name:
«file_name.phl»
«file_name.cgi»
«file_path/file_name.phl»
"/file_path/file_name.html"
«httр://domain/file_path/file_name.html»

[param]:
phl,   exist,   head
abs,   no_abs,   no_eval
no_strict,   open,   decode
no_decode,   cgi,   socket
fork,   thread

дополнительные параметры и зависимости:
phl [.phl] <= exist, head, abs, decode
cgi [.cgi] <= require, decode
open <= decode, abs
socket <= exist, head, no_abs, decode, no_decode
fork <= waitpid, no_waitpid
thread <= join, detach

Первый аргумент 'file_name' кроме имени файла может содержать зарезервированные слова "JOIN", "CONFIG" или "TIMER".

Если файл 'file_name' имеет расширение '.phl', то такой файл идентифицируется, как файл формата PHL. Расширение может быть изменено в настройках с помощью $phl{pl}.

При вызове функции 'include()' в неопределенном контексте результат выполнения кода Perl помещается в тело документа внутри функции print(). При скалярном или списковом контексте результат возвращается в виде запрашиваемого значения переменной или списка значений соответственно.

 1 <%pl
 2    include("file_name.phl");
 3    my $result = include("file_name.phl");
 4    my @result = include("file_name.phl");
 5 %>

Второй аргумент функции 'include()' может содержать один или несколько специальных управляющих параметров.

• Параметр 'phl'


Данный параметр указывает обработчику, что код, содержащийся в подключаемом файле, представляет собой документ формата PHL.

Данные файла отправляются в анализатор, где преобразуются в perl-код и передаются 'eval'.

Параметр 'phl' выполняет аналогичные действия, если бы мы в имени включаемого файла просто указали расширение '.phl' (расширение можно изменить в настройках в '$phl{pl}').

 1 <%pl
 2    include("file_name.txt", "phl");
 3    my $result = include("file_name.html", "phl decode=utf-8");
 4    my @result = include("file_name", "phl abs");
 5 %>

• Параметр 'exist' ('ex')


Позволяет проверить существование файла.

 1 <%pl
 2    my $exist_file = include("$file_name", "exist");
 3    if ($exist_file) {
 4        print "Файл $file_name найден";
 5    } else {
 6        print "Файл $file_name не найден";
 7    }
 8 %>

• Параметр 'head' ('hd')


Возвращает список из 5 элементов: Content type, Document length, Modified time, Expires, Server.

 1 <%pl
 2    my @head = include("$file_name", "head");
 3 %>

• Параметр 'abs'


Если присутствует параметр 'abs', осуществляется преобразование относительных ссылок, указанных в файле, в абсолютные.

 %pl include("$file_name", "abs");

• Параметр 'no_eval' ('ne')


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

 <%pl include("$file_name", "no_eval") %>

• Параметр 'no_strict' ('ns')


Если указан параметр 'no_strict', то на код загружаемого файла '$file_name' действие прагмы 'use strict' не распространяется.

 1 <%pl
 2    include("$file_name", "ns");
 3 %>

• Параметр 'open' ( 'on' )


Как и функция 'open()', служит для открытия файла и извлечения из него каких-либо данных (возможность записи данных в файл отсутствует).

 1 <%pl
 2    include("$file_name", "open");
 3    my $result = include("$file_name", "open decode=koi8-r");
 4    my @result = include("$file_name", "on, decode=cp1251, abs");
 5 %>

• Параметр 'decode' ('dc')


При наличии параметра 'decode' данные из указанной в параметрах кодировки (к примеру, 'decode=cp1251') декодируются во внутренний формат Perl.

Если кодировка не указана или отсутствует параметр 'decode', то при декодировании подразумевается, что кодировка включаемого файла соответствует $phl{encoding_in}, указанной в настройках phl.pm (или config.phl).

Если кодировка результирующего документа отлична от 'utf-8', то дополнительно осуществляется кодирование данных в кодировку $phl{encoding_out}, указанную в настройках phl.pm (или config.phl).
Кодирование и декодирование данных осуществляется с использованием стандартного модуля 'Encode.pm'.

• Параметр 'cgi'


Данный параметр предназначен для подключения cgi-скриптов, написанных на Perl.

 1 <%pl
 2    include("file_name.cgi");
 3    include("$file_name", "cgi");
 4    include("$file_name", "cgi require"); 
 5    include("file_name.cgi", "decode=cp866");
 6 %>

• Параметр 'socket' ('sk')


Применяется для загрузки web-документа с помощью стандартного модуля 'IO::Socket::INET'

 1 <%pl
 2    include("file_name.html", "socket");
 3    include("http://domain/");
 4    my $text = include("http://domain/file_path/file_name.html", "decode=cp1251");
 5    my @result = include("$file_name", "decode no_abs");
 6 %>

Если адрес включаемого в документ файла начинается с http или ftp, то указывать параметр 'socket' не обязательно.

Совместно с параметром 'socket' могут применяться дополнительные параметры 'exist', 'head', 'no_abs', 'decode', 'no_decode'.

  • дополнительный параметр 'exist' ('ex')

Позволяет проверить существование домена, файла, адреса.

 1  <%pl
 2     my @include_name_file = (
 3        'dir1/name_file.html',
 4        '/dir2/name_file.php',
 5        'http://www.yandex.ru',
 6        'http://www.yandex/eklmnfjoeqxngsitwf.html',
 7        'http://eklmnfjoeqxngsitwfhoevd.ru'
 8     );
 9   
 10    foreach my $name_file (@include_name_file) {
 11       my $ex = include("$name_file", "socket exist");
 12       if ($ex) {
 13          print "Файл '$name_file' найден<br>";
 14       } elsif (!defined $ex) {
 15          print "Ресурс '$name_file' не отвечает<br>";   
 16       } else {
 17          print "Файл '$name_file' не найден<br>";
 18       }
 19    }
 20 %>

  • дополнительный параметр 'head' ('hd')

Возвращает заголовок документа

 1  <%pl
 2     foreach my $name_file (@test_name_file) {
 3        my head = include("$name_file", "socket head");
 4        if ($#head) {
 5           print "Заголовок от '$name_file' получен => '@head[0..3]'<br>";
 6        } else {
 7           print "Заголовка от '$name_file' нет => '@head'<br>";
 8        }
 9     }
 10 %>

  • дополнительный параметр 'no_abs' ('na')

По умолчанию, все относительные ссылки заменяются на абсолютные, но если указан параметр 'no_abs', то этого не происходит.

  %pl include("$file_name", "socket no_abs");

  • дополнительный параметр 'decode' ('dc')

Служит для декодирования документов из кодировки, указанной параметром 'decode', во внутренний формат Perl и далее в кодировку, указанную в настройках в $phl{encoding_out}.

Если параметр 'decode' используется без указания исходной кодировки запрашиваемого файла, то декодирование осуществляется с учетом кодировки, указанной в заголовке файла в 'charset' (при наличии).

Если параметр 'decode' не используется, по умолчанию подразумевается, что наш файл в кодировке utf-8.

При использовании параметра 'no_decode' ('nd') никакого декодирования данных не происходит.

 1  <%pl
 2     include("http://www.rbc.ru", "decode=utf-8");
 3     include("http://www.mail.ru", "decode");
 4     my $html_text1 = include("http://ru.motorsport.com");
 5     my $html_text2 = include("http://www.google.com", "nd");
 6  %>

• Параметр 'fork' ('fk')


Код загружаемого файла выполняется в параллельном дочернем процессе, созданном в результате запуска 'fork()'.

 1  <%pl
 2     include("$file_name", "fork");
 3  %>

Результат выполнения параллельного процесса можно вернуть в родительский, используя 'return' в тексте инструкции включаемого файла.

 1  <%pl
 2     <font color=#646464><I># Код дочернего процесса $phl_var{name}</I></font>
 3     my $f = "Передаваемые данные";
 4     sleep 1;
 5     return $f;
 6  %>

В третьем аргументе функции 'include()' можно указать уникальное имя дочернего процесса, чтобы затем обратиться за результатом выполнения дочернего процесса «по имени».

 1  <%pl
 2     include("$file_name", "fork", "f1");
 3  %>

  • дополнительный параметр 'waitpid' ('wd')

Для того, чтобы вернуть результат выполнения дочернего процесса в точку вызова функции 'include()', необходимо дополнительно к параметру 'fork' указать параметр 'waitpid' или в качестве третьего аргумента функции 'include()' указать 'waitpid'.

Результат отработки параллельного процесса можно вернуть обратно в родительский процесс, вызвав 'include()' в скалярном или списковом контексте.

 1  <%pl
 2     $result = include("$file_name", "fork waitpid");
 3     @result = include("$file_name", "fork", "waitpid");
 4  %>

На самом деле, можно вообще отказаться от параметра 'waitpid', как во втором так и в третьем аргументе. В таком случае, программа всё равно будет ждать завершения дочернего процесса, а функция 'include()' получается менее громоздкой.

 1  <%pl
 2     @result = include("$file_name", "fork", "");
 3     $result = include("$file_name", "fk");
 4  %>

  • дополнительный параметр 'no_waitpid' ('nw')

Результат выполнения процесса вернуть не удастся, если только, не попробовать что-либо записать в файл или вывести на экран.

 1  <%pl
 2     include("$file_name", "fork no_waitpid");
 3     include("$file_name", "fork", "no_waitpid");
 4  %>

  • аргумент 'JOIN'

Для обращения за результатом выполнения дочернего процесса можно использовать функцию 'include()', где в качестве первого аргумента необходимо указать зарезервированное слово 'JOIN', вторым аргументом — имя или имена дочерних процессов.

 1  <%pl
 2     include("$file_name", "fork", "f1");
 3    
 4     # Далее может следовать тело программы с некоторым кодом
 5  
 6     my $rezult = include("JOIN", "f1");
 7  %>

Вернуть результаты нескольких или даже всех параллельных процессов можно обратившись к хэшу, ключами которого будут имена процессов, значениями — результаты их выполнения.

 1  <%pl
 2     my %join_2_3 = include("JOIN", "f2 f3"); 
 3     print "Результат процесса 'f2' = $join_2_3{f2}<br>";
 4  
 5     my %join_all = include("JOIN");
 6     foreach my $key(keys(%join_all)) {
 7        if (ref $join_all{$key}) {
 8           my @result = @{$join_all{$key}};
 9           print "Результат процесса '$key' = '$join_all{$key}' => ";
 10          print "и первый разыменованный элемент массива = '$result[0]'<br>";
 11       } else {
 12          print "Результат процесса '$key' = '$join_all{$key}'<br>";
 13       }
 14    }
 15 %>

• Параметр 'thread' ('td')


Создается, так называемая, «нить» («поток») — своеобразная ветка процесса, в которой возможно выполнение кода параллельно коду породившего нить процесса.

Для создания нити используется стандартный модуль 'thread' (в свою очередь, Perl должен быть настроен на работу с тредами).

 1  <%pl
 2     include("$file_name", "thread");
 3  %>

Как и в случае с параметром 'fork', при использовании нитей существует возможность вернуть результат выполнения созданной нити, как в точку вызова функции 'include()', так и в произвольную точку программы или вообще «забыть» о результате, ничего не возвращая.

  • дополнительный параметр 'join' ('jn')

Результат выполнения нити возвращается в точку вызова, при этом родительский процесс временно прекращает своё выполнение и ждет получения данных (от созданных потоков).

 1  <%pl
 2     $result = include("$file_name", "thread join");
 3     @result = include("$file_name", "thread", "join");
 4     %result = include("$file_name", "thread");
 5  %>

  • дополнительный параметр 'detach' ('dh')

Нить создается, но что в ней происходит основная ветка процесса не знает.

 1  <%pl
 2     include("$file_name", "thread detach");
 3     include("$file_name", "thread", "detach");
 4  %>

Вернуть данные в любую точку основной ветки процесса можно, присвоив нити имя (по аналогии с дочерним процессом, создаваемым параметром 'fork').

 1  <%pl
 2     include("$file_name", "thread", "t1");
 3     include("$file_name", "thread", "t2");
 4     include("$file_name", "thread", "t3");
 5    
 6     my $rezult = include("JOIN", "t2");
 7     print "Результат нити 't2' = '$rezult'<br>";
 8  
 9     my %join = include("JOIN", "t1 t3"); 
 10    print "Результат нити 't1' = '$join{t1}'<br>";
 11    print "Результат нити 't3' = '$join{t3}'<br>";
 12 %>

• Собственные параметры


При желании можно определить свои собственные (дополнительные) параметры или переопределить существующие. Это реализуется с помощью специально оформленных модулей.

Так, к примеру, с помощью модуля 'HTML::Phl::Utilit' и параметра 'analys' ('as') появляется возможность просмотреть сформированный анализатором код perl включаемого файла перед его выполнением eval.

Пример:

 1  %pl -ev use HTML::Phl::Utilit;
 2  
 3  <%pl
 4     include("$file_name", "as");
 5  %>

Листинг
 1  Текст HTML<br>
 2  
 3  <%pl
 4     my $test = "Текст Perl<br>";
 5     print ("$test");
 6  %>
 7  
 8  Текст HTML<br>


Результат
 1  print <<'[HTML]';
 2  Текст HTML<br>
 3   
 4  [HTML]
 5     my $test = "Текст Perl<br>";
 6     print ("$test");
 7  print <<'[HTML]';
 8   
 9  Текст HTML<br>
 10  [HTML]



Модули-расширения PHL ^ 


Для достижения большей гибкости работы в PHL реализована возможность задавать собственные указатели инструкции [sh], ключи [keys], первый аргумент [include] и параметры [param] функции 'include()'.

<%[sh] [keys]

include("[include]", "[param]");

%>

Новые ключи, параметры и указатели импортируются в phl.pm из специально написанных для данных целей модулей.

Для примера в PHL включены 4 модуля:

   use HTML::Phl::Utilit;
   use HTML::Phl::Psimple;
   use HTML::Phl::Php;
   use HTML::Phl::Ru;

Модули можно подключить как в файле 'phl.pm' или 'config.phl', так и в файле PHL.

 1  %pl -ev use HTML::Phl::Utilit
 2  
 3  <%pl
 4     # код perl
 5  %>

• Модуль 'HTML::Phl::Utilit'


Модуль экспортирует в программу 5 ключей, 2 параметра и 2 аргумента для функции 'include()'.

[keys]:
-listing
-analys
-config
-timer
-no_timer

[param]:
listing
analys

[include]:
CONFIG
TIMER

Ключи '-listing' [ '-lt' ] и '-analys' [ '-as' ] и параметры 'listing' ( 'lt' ) и 'analys' ( 'as' ) дают, возможность просмотреть листинг программы или сформированный анализатором код perl перед его выполнением eval.

Ключ '-listing' [ '-lt' ]

 1  Текст HTML 1
 2  <br><br>
 3  
 4  <%pl -lt
 5     my $test = "Текст Perl<br>";
 6     print "$test";
 7  %>
 8  <br>
 9  
 10 Текст HTML 2

Результат
Текст HTML 1

 1   my $test = "Текст Perl<br>";
 2   print "$test";

Текст HTML 2

Ключ '-analys' [ '-as' ]

 1  %pl -as
 2  
 3  <%pl
 4     my $test = "Текст Perl<br>";
 5     print ("$test");
 6  %>
 7  
 8  Текст HTML и <%pl= $test %>

Результат
 1  ;
 2  print <<'[HTML]';
 3   
 4  [HTML]
 5     my $test = "Текст Perl<br>";
 6     print ("$test");
 7  print <<'[HTML]';
 8   
 9  [HTML]
 10  print <<'[HTML]' =~ /(.*)/;
 11  Текст HTML и
 12  [HTML]
 13  print($test);


Ключ '-config' [ '-cf' ] или аргумент 'CONFIG' функции 'include()' выводят на печать хэш %phl конфигурационных переменных.

 1  %pl -config
 2  
 3  или так
 4  
 5  <%pl
 6     include("CONFIG");
 7  %>

Результат

Конфигурационные переменные


bottom = ''
bufer = '1'
config = 'config.phl'
config_path = ''
encoding_in = 'utf8'
encoding_out = 'utf8'
finde_config = 'yes'
header = 'Content-type: text/html; charset=utf-8'
index = 'index.phl'
ln = '%'
locale = 'utf8'
lt = '<%'
pl = 'phl'
rt = '%>'
script_dir = ''
sh = 'pl'
threads = '1'
timer = '0'
top = ''

Ключи '-timer' [ '-tm' ] и '-no_timer' [ '-nt' ] позволяют изменить механизм вывода на экран временных промежутков работы компонентов программы, а используя аргумент 'TIMER' функции 'include()' можно задать свой таймер.

 1 <%pl
 2    # запуск встроенного таймера
 3    %pl -timer
 4
 5    # остановка встроенного таймера
 6    %pl -nt
 7 %>

Пример
1. Запускаем timer ключем '-timer' или '-tm'
timer = 4

2. Проверяем результат на тестовом 'include()' (без параметров)

Результат =>

• Время — 0.248574 [0.226931 ] < INCLUDE_BEGINE ()


• Время — 0.248953 [0.227302 ] < INCLUDE_END ()


test: timer = 4

3. Выключаем timer ключем '-no_timer' или '-nt'

4. Проверяем результат на тестовом 'include()'

Результат => test: timer = 0

 1 <%pl
 2    # пример создания своего таймера
 3    include("TIMER", "имя таймера");
 4 %>

Пример
Создаем таймер 1

• Время — 0.000005 < TIMER (name_timer_1)


ждем некоторое время — sleep 0.2

• Время — 0.200440 < TIMER (name_timer_1)



Новый таймер 2

• Время — 0.000004 < TIMER (name_timer_2)


ждем некоторое время — sleep 0.5

• Время — 0.701001 < TIMER (name_timer_1)


• Время — 0.500496 < TIMER (name_timer_2)



Новый таймер 3

• Время — 0.000003 < TIMER (name_timer_3)


ждем некоторое время — sleep 0.35

• Время — 1.051648 < TIMER (name_timer_1)


• Время — 0.851139 < TIMER (name_timer_2)


• Время — 0.350579 < TIMER (name_timer_3)




• Модуль 'HTML::Phl::Php'


Экспортирует указатель 'php', превращая указатель инструкции '<%pl' в '<%php', для возможности работы с кодом языка программирования PHP;

 1  %pl -ev use HTML::Phl::Php;
 2  
 3  %pl our $pl = 5;
 4  
 5  Исходная переменная PERL: $pl = <b>'<%pl= $pl %>'</b>.
 6  <br><br>
 7  
 8  <%php
 9     echo "Значение переменной $pl передаем в PHP ($pl -> $php).<br>";
 10    OUT_PERL($pl -> $php);
 11   
 12    echo "<li>Переменная $php = $php.</li><br>";
 13  
 14    echo "В PHP изменяем значение переменной: $php = 2 * $php + 1.5.<br><br>";
 15    $php = 2 * $php + 1.5;
 16  
 17    echo "Возвращаем значение переменной $php в PERL ($php -> $pl).<br>";
 18    IN_PERL($php -> $pl);
 19 %>
 20  
 21  <li>Результирующая переменная PERL: $pl = <b>'<%pl= $pl %>'</b></li>.

Результат
Исходная переменная PERL: $pl = '5'.

Значение переменной $pl передаем в PHP ($pl -> $php).
Переменная $php = 5.
В PHP изменяем значение переменной: $php = 2 * $php + 1.5.

Возвращаем значение переменной $php в PERL ($php -> $pl).
Результирующая переменная PERL: $pl = '11.5'.


• Модуль 'HTML::Phl::Ru'


Экспортирует указатель 'рус', превращая указатель инструкции '<%pl' в '<%рус', позволяя работать с некоторыми функциями и операторами кириллического написания.

 1  %pl -ev use HTML::Phl::Ru;
 2  
 3  <%рус
 4     my @имена_файлов = (
 5        'file_exist.phl',
 6        'http://www.pushkinmuseum.ru',
 7        'http://www.pushkinmuseum.ru/467899',
 8        'http://eklmn12344556778.ru'
 9     );
 10   
 11    foreach my $имя_файла (@имена_файлов) {
 12       my $найдено = ВКЛЮЧИТЬ("$имя_файла", "socket exist");
 13       ЕСЛИ ($найдено) {
 14          ПЕЧАТЬ "'$имя_файла' - <B>найден</B><br>";
 15       } ИЛИ ЕСЛИ (!defined $найдено) {
 16          ПЕЧАТЬ "'$имя_файла' - <B>не отвечает</B><br>";   
 17       } ИНАЧЕ {
 18          ПЕЧАТЬ ("'$имя_файла' - <B>не найден</B><br>");
 19       }
 20    }
 21 %>

Результат
'file_exist.phl' — не найден
'http://www.pushkinmuseum.ru' — найден
'http://www.pushkinmuseum.ru/467899' — не найден
'http://eklmn12344556778.ru' — не отвечает


• Модуль 'HTML::Phl::Psimple'


Экспортирует параметр 'Simple' ['sl'] для работы со стандартным модулем Perl 'LWP::Simple';

Структура модулей-расширений


Для возможности экспорта ключей, параметров и указателей модули должны размещаться в определенной папке (по умолчанию — в 'Phl', находящейся рядом с основным файлом программы 'phl.pm') и содержать двумерный хэш '%phl_import', в котором ключами второго хеша будут экспортируемые ключи, параметры и указатели.

Хэш '%phl_import' может включать 5 ключей — 'sh', 'key', 'param', 'include' и 'eval'.

 1    our %phl_import = (
 2       key     => {
 3                    tm    => \&HTML::Phl::Utilit::key_timer,
 4                    im    => \&HTML::Phl::Utilit::print_import,
 5                  },
 6       include => {
 7                    TIMER  => \&HTML::Phl::Utilit::my_timer,
 8                    CONFIG => \&HTML::Phl::Utilit::config,
 9                  },
 10       param  => {lt    => \&HTML::Phl::Utilit::open_listing},
 11       sh     => {'рус'  => \&HTML::Phl::Ru::ru_perl},
 12       eval   => {as    => \&HTML::Phl::Utilit::eval_code}
 13   );


Конфигурационные настройки ^ 


Конфигурационные файлы 'config.phl' позволяют переопределять базовые переменные, указанные в 'phl.pm'. Их можно размещать в любой web-директории, содержащей PHL файлы.

Конфигурационные файлы разрабатываются в формате Perl и содержат значения ключей хеша %phl.

config.phl
# Расширение файлов, обрабатываемых анализатором программы, как файлы формата PHL (по умолчанию принято расширение — '.phl')
$phl{pl} = 'phl';

# Имя файла, которое ищет функция 'include()' в директории, если не указан загружаемый файл, к примеру domain.ru/file_path
$phl{index} = 'index.phl';

# Осуществлять или не осуществлять поиск конфигурационных файлов 'config.phl' в директории загружаемых include() файлов [ yes/no ]
$phl{finde_config} = "yes";

# Определение указателей инструкций [ по умолчанию, '<%pl code_perl %>', '%pl line_code_perl' ]
$phl{lt} = '<%';
# начало блока инструкции
$phl{rt} = '%>';
# конец блока инструкции
$phl{ln} = '%';
# линейная инструкция
$phl{sh} = 'pl';
# указатель принадлежности к языковой конструкции (в данном случае к perl)

# Заголовок документа [ к примеру, «Content-type: text/html; charset=utf-8\n\n»; $phl_header = "" — нет заголовка ]
$phl{header} = "";

# Верхний колонтитул
$phl{top} = "";

# Нижний колонтитул
$phl{bottom} = "";

# Сброс буфера [ «1» соответствует => $| = 1, «0» соответствует => $| = 0 ]
$phl{bufer} = 1;

# Использование потоков (нитей) [ 1/0 ]
$phl{threads} = 1;

# Подсчитывается время загрузки компонентов [ различная степень детализации => «0» — нет, «1»...«4» — да ]
$phl{timer} = 0;

# Кодировка файлов [ cp1251, utf8, koi8-r, iso-8859-5, cp866… ]
$phl{encoding_in} = "utf8"; # кодировка загружаемых include() файлов
$phl{encoding_out} = "utf8"; # кодировка результирующего документа
$phl{locale} = "utf8"; # кодировка имен файлов файловой системы




Дистрибутив PHL ^ 

camel
Модуль 'HTML::Phl' вместе с дополнительными модулями-расширениями, тестами и примерами можно скачать здесь.

При желании опробовать работу модуля в ОС Android, необходимо установить SL4A, позволяющий запускать в данной среде perl-программы, в частности веб-сервер, способный генерировать HTML страницы по запросам Perl. Как написать свой веб-сервер на Perl под Android можно ознакомиться здесь или скачать немного измененный под работу с PHL вариант здесь.
Tags:
Hubs:
+4
Comments7

Articles