mirror of
https://github.com/php/doc-ru.git
synced 2026-03-25 16:22:18 +01:00
236 lines
6.0 KiB
XML
236 lines
6.0 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: 0e8db71fa8529a320a17d6c57c57f02626844ffc Maintainer: sergey Status: ready -->
|
||
<!-- Reviewed: no -->
|
||
|
||
<chapter xml:id="parle.examples" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||
&reftitle.examples;
|
||
|
||
<section xml:id="parle.examples.lexer">
|
||
<title>Примеры использования лексера</title>
|
||
<example>
|
||
<title>Токенизация списка целых чисел через запятую</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
use Parle\Token;
|
||
use Parle\Lexer;
|
||
use Parle\LexerException;
|
||
|
||
/* name => id */
|
||
$token = array(
|
||
"COMMA" => 1,
|
||
"CRLF" => 2,
|
||
"DECIMAL" => 3,
|
||
);
|
||
/* id => name */
|
||
$tokenIdToName = array_flip($token);
|
||
|
||
$lex = new Lexer;
|
||
$lex->push("[\x2c]", $token["COMMA"]);
|
||
$lex->push("[\r][\n]", $token["CRLF"]);
|
||
$lex->push("[\d]+", $token["DECIMAL"]);
|
||
$lex->build();
|
||
|
||
$in = "0,1,2\r\n3,42,5\r\n6,77,8\r\n";
|
||
|
||
$lex->consume($in);
|
||
|
||
do {
|
||
$lex->advance();
|
||
$tok = $lex->getToken();
|
||
|
||
if (Token::UNKNOWN == $tok->id) {
|
||
throw new LexerException("Неизвестный токен '{$tok->value}' по смещению {$lex->marker}.");
|
||
}
|
||
|
||
echo "ТОКЕН: ", $tokenIdToName[$tok->id], PHP_EOL;
|
||
} while (Token::EOI != $tok->id);
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
<example>
|
||
<title>Токенизировать оператор присваивания</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
use Parle\{Token, Lexer};
|
||
|
||
$lex = new Lexer;
|
||
|
||
$lex->push("\$[a-zA-Z_][a-zA-Z0-9_]*", 1);
|
||
$lex->push("=", 2);
|
||
$lex->push("\d+", 3);
|
||
$lex->push(";", 4);
|
||
|
||
$lex->build();
|
||
|
||
$lex->consume('$x = 42; $y = 24;');
|
||
|
||
|
||
do {
|
||
$lex->advance();
|
||
$tok = $lex->getToken();
|
||
var_dump($tok);
|
||
} while (Token::EOI != $tok->id);
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</section>
|
||
<section xml:id="parle.examples.parser">
|
||
<title>Пример использования парсера</title>
|
||
<example>
|
||
<title>Простой калькулятор</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
use Parle\{Parser, ParserException, Lexer, Token};
|
||
|
||
$p = new Parser;
|
||
$p->token("INTEGER");
|
||
$p->left("'+' '-' '*' '/'");
|
||
|
||
$p->push("start", "exp");
|
||
$prod_add = $p->push("exp", "exp '+' exp");
|
||
$prod_sub = $p->push("exp", "exp '-' exp");
|
||
$prod_mul = $p->push("exp", "exp '*' exp");
|
||
$prod_div = $p->push("exp", "exp '/' exp");
|
||
$p->push("exp", "INTEGER"); /* Индекс производства не используется. */
|
||
|
||
$p->build();
|
||
|
||
$lex = new Lexer;
|
||
$lex->push("[+]", $p->tokenId("'+'"));
|
||
$lex->push("[-]", $p->tokenId("'-'"));
|
||
$lex->push("[*]", $p->tokenId("'*'"));
|
||
$lex->push("[/]", $p->tokenId("'/'"));
|
||
$lex->push("\\d+", $p->tokenId("INTEGER"));
|
||
$lex->push("\\s+", Token::SKIP);
|
||
|
||
$lex->build();
|
||
|
||
$exp = array(
|
||
"1 + 1",
|
||
"33 / 10",
|
||
"100 * 45",
|
||
"17 - 45",
|
||
);
|
||
|
||
foreach ($exp as $in) {
|
||
if (!$p->validate($in, $lex)) {
|
||
throw new ParserException("Не удалось проверить ввод");
|
||
}
|
||
|
||
$p->consume($in, $lex);
|
||
|
||
while (Parser::ACTION_ERROR != $p->action && Parser::ACTION_ACCEPT != $p->action) {
|
||
switch ($p->action) {
|
||
case Parser::ACTION_ERROR:
|
||
throw new ParserException("Parser error");
|
||
break;
|
||
case Parser::ACTION_SHIFT:
|
||
case Parser::ACTION_GOTO:
|
||
case Parser::ACTION_ACCEPT:
|
||
break;
|
||
case Parser::ACTION_REDUCE:
|
||
switch ($p->reduceId) {
|
||
case $prod_add:
|
||
$l = $p->sigil(0);
|
||
$r = $p->sigil(2);
|
||
echo "$l + $r = " . ($l + $r) . "\n";
|
||
break;
|
||
case $prod_sub:
|
||
$l = $p->sigil(0);
|
||
$r = $p->sigil(2);
|
||
echo "$l - $r = " . ($l - $r) . "\n";
|
||
break;
|
||
case $prod_mul:
|
||
$l = $p->sigil(0);
|
||
$r = $p->sigil(2);
|
||
echo "$l * $r = " . ($l * $r) . "\n";
|
||
break;
|
||
case $prod_div:
|
||
$l = $p->sigil(0);
|
||
$r = $p->sigil(2);
|
||
echo "$l / $r = " . ($l / $r) . "\n";
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
$p->advance();
|
||
}
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
<example>
|
||
<title>Разобрать слова из предложения</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
use Parle\{Lexer, Token, Parser, ParserException};
|
||
|
||
$p = new Parser;
|
||
$p->token("WORD");
|
||
$p->push("START", "SENTENCE");
|
||
$p->push("SENTENCE", "WORDS");
|
||
$prod_word_0 = $p->push("WORDS", "WORDS WORD");
|
||
$prod_word_1 = $p->push("WORDS", "WORD");
|
||
$p->build();
|
||
|
||
$lex = new Lexer;
|
||
$lex->push("[^\s]{-}[\.,\:\;\?]+", $p->tokenId("WORD"));
|
||
$lex->push("[\s\.,\:\;\?]+", Token::SKIP);
|
||
$lex->build();
|
||
|
||
$in = "Dis-moi où est ton papa?";
|
||
$p->consume($in, $lex);
|
||
do {
|
||
switch ($p->action) {
|
||
case Parser::ACTION_ERROR:
|
||
throw new ParserException("Error");
|
||
break;
|
||
case Parser::ACTION_SHIFT:
|
||
case Parser::ACTION_GOTO:
|
||
/* var_dump($p->trace());*/
|
||
break;
|
||
case Parser::ACTION_REDUCE:
|
||
$rid = $p->reduceId();
|
||
if ($rid == $prod_word_1) {
|
||
var_dump($p->sigil(0));
|
||
} if ($rid == $prod_word_0) {
|
||
var_dump($p->sigil(1));
|
||
}
|
||
break;
|
||
}
|
||
$p->advance();
|
||
} while (Parser::ACTION_ACCEPT != $p->action);
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</section>
|
||
</chapter>
|
||
<!-- Keep this comment at the end of the file
|
||
Local variables:
|
||
mode: sgml
|
||
sgml-omittag:t
|
||
sgml-shorttag:t
|
||
sgml-minimize-attributes:nil
|
||
sgml-always-quote-attributes:t
|
||
sgml-indent-step:1
|
||
sgml-indent-data:t
|
||
indent-tabs-mode:nil
|
||
sgml-parent-document:nil
|
||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||
sgml-exposed-tags:nil
|
||
sgml-local-catalogs:nil
|
||
sgml-local-ecat-files:nil
|
||
End:
|
||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||
vim: et tw=78 syn=sgml
|
||
vi: ts=1 sw=1
|
||
-->
|