yosymfony / parser-utils
解析器实用工具
Requires
- php: >=7.1
Requires (Dev)
- phpunit/phpunit: ^6
This package is auto-updated.
Last update: 2024-09-13 05:04:32 UTC
README
这是一个用于在PHP中编写递归下降解析器的库。
要求
- PHP >= 7.1
安装
首选的安装方法是 composer
composer require yosymfony/parser-utils
示例
首先,您需要创建一个词法分析器。这个分析器将识别令牌
use Yosymfony\ParserUtils\BasicLexer; $lexer = new BasicLexer([ '/^([0-9]+)/x' => 'T_NUMBER', '/^(\+)/x' => 'T_PLUS', '/^(-)/x' => 'T_MINUS', '/^\s+/' => 'T_SPACE', // We do not surround it with parentheses because // this is not meaningful for us in this case ]);
其次,您需要一个解析器来消费词法分析器提供的令牌。`AbstractParser` 类包含一个名为 `parseImplementation` 的抽象方法,该方法接收一个 `TokenStream` 作为参数。
use Yosymfony\ParserUtils\AbstractParser; class Parser extends AbstractParser { protected function parseImplementation(TokenStream $stream) { $result = $stream->matchNext('T_NUMBER'); while ($stream->isNextAny(['T_PLUS', 'T_MINUS'])) { switch ($stream->moveNext()->getName()) { case 'T_PLUS': $result += $stream->matchNext('T_NUMBER'); break; case 'T_MINUS': $result -= $stream->matchNext('T_NUMBER'); break; default: throw new SyntaxErrorException("Something went wrong"); break; } } return $result; } }
现在,您可以查看结果
$parser = new Parser($lexer); $parser->parse('1 + 1'); // 2
BasicLexer 类
词法分析器负责识别令牌。这个分析器按行工作。如果您想为输入的每一行生成一个特殊的 `T_NEWLINE` 令牌,请在令牌化之前调用 `$lexer->generateNewlineTokens()`。您可以使用 `setNewlineTokenName` 方法设置此特殊令牌的名称。
$lexer = new BasicLexer([...]); $lexer->generateNewlineTokens() ->setNewlineTokenName('T_NL'); $lexer->tokenize('...');
此外,还有一个特殊的令牌 `T_EOS`,它确定输入字符串的结束。要启用此功能,请在令牌化之前调用 `$lexer->generateEosToken()`。您可以使用 `setEosTokenName` 方法设置此特殊令牌的名称。
$lexer = new BasicLexer([...]); $lexer->generateEosToken() ->setEosTokenName('T_MY_EOS'); $lexer->tokenize('...');
TokenStream 类
此类允许您处理由词法分析器返回的令牌列表。
-
moveNext: 将指针向前移动一个令牌。返回一个 `Token` 对象或 `null`(如果没有更多令牌)。例如:`$ts->moveNext()`。
-
matchNext: 匹配下一个令牌并返回其值。此方法将指针向前移动一个令牌。如果下一个令牌不匹配,则抛出 `SyntaxErrorException` 异常。例如:`$number = $ts->matchNext('T_NUMBER')`。
-
isNext: 检查下一个令牌是否与作为参数传递的令牌名称匹配。例如:`$ts->isNext('T_PLUS') // true 或 false`。
-
skipWhile: 在令牌与作为参数传递的令牌名称匹配时跳过令牌。此方法将指针向前移动 "n" 个令牌,直到最后一个与令牌名称匹配的令牌。例如:`$ts->skipWhile('T_PLUS')`
-
skipWhileAny: 在令牌与作为参数传递的令牌名称之一匹配时跳过令牌。此方法将指针向前移动 "n" 个令牌,直到最后一个与一个或多个令牌名称匹配的令牌。例如:`$ts->skipWhileAny(['T_PLUS', 'T_MINUS'])`
-
isNextSequence: 检查流中的后续令牌是否与令牌序列匹配。例如:`$ts->isNextSequence(['T_NUMBER', 'T_PLUS', 'T_NUMBER']) // true 或 false`。
-
isNextAny: 检查传递的令牌中的任何一个是否是下一个令牌。例如:`$fs->isNextAny(['T_PLUS', 'T_SUB']) // true 或 false`。
-
hasPendingTokens: 有待处理的令牌吗?例如:`$fs->hasPendingTokens() // true 或 false`。
-
reset: 将流重置到开始位置。
令牌
令牌是 `Token` 类的实例,该类包含以下方法
- getName: 返回令牌的名称。例如:`T_SUM`。
- getValue: 返回令牌的值。
- getLine: 返回令牌所在的行。
单元测试
您可以使用以下命令运行单元测试
$ cd parser-utils $ composer test
许可证
此库是开源软件,受MIT许可证许可。