pvandommelen / parser
PHP解析器生成器
Requires
- php: ~5.5 || ~7.0
- ext-mbstring: *
Requires (Dev)
- phpunit/phpunit: 5.3.*
This package is auto-updated.
Last update: 2024-09-23 20:33:22 UTC
README
用PHP编写的解析器生成器。
特性
支持回溯。
检测左递归。
直接匹配字符串,因此不包含词法分析(分词)步骤
通用用法
应使用可用的辅助类及其静态方法。
PeterVanDommelen\Parser\ParserHelper::compile(ExpressionInterface $expression)
PeterVanDommelen\Parser\ParserHelper::compileWithGrammar(ExpressionInterface $expression, Grammar $grammar)
这些方法接受一个表达式(见下文哪些可用)和一个可能的语法(见下文)。返回值是提供一种方法的解析器
PeterVanDommelen\Parser\Parser\ParserInterface::parse(string $string)
如果解析器无法匹配字符串,则parse方法将返回null。解析器始终从开头匹配。如果成功匹配,则返回与解析表达式对应的结果对象。
结果对象实现了ExpressionResultInterface,该接口具有以下两个描述匹配字符串的方法
PeterVanDommelen\Parser\Expression\ExpressionResultInterface::getString()
PeterVanDommelen\Parser\Expression\ExpressionResultInterface::getLength()
具体实现取决于使用的表达式,可能还有其他方法可用,请参阅示例。
可用表达式
常量
PeterVanDommelen\Parser\Expression\Constant\ConstantExpression
new ConstantExpression(string $string)
基本终端。
连接
PeterVanDommelen\Parser\Expression\Concatenated\ConcatenatedExpression
new ConcatenatedExpression(ExpressionInterface[] $parts);
示例
$result = ParserHelper::compile(new ConcatenatedExpression(array(
new ConstantExpression("a"),
new ConstantExpression("b"),
)))->parse("abc");
$result->getString(); // "ab"
$result->getPart(0)->getString(); // "a"
$result->getPart(1)->getString(); // "b"
替代
PeterVanDommelen\Parser\Expression\Alternative\AlternativeExpression
new AlternativeExpression(ExpressionInterface[] $alternatives)
匹配以下表达式之一。
$result = ParserHelper::compile(new AlternativeExpression(array(
new ConstantExpression("a"),
new ConstantExpression("b"),
)))->parse("abc");
$result->getString(); // "a"
$result->getKey(); // 0
$result->getResult()->getString(); // "a"
重复
PeterVanDommelen\Parser\Expression\Repeater\RepeaterExpression
new RepeaterExpression(ExpressionInterface $inner_expression, bool $is_lazy = false, int $minimum = 0, int|null $maximum = null)
重复内部表达式,指定最小和最大次数。
$result = ParserHelper::compile(new RepeaterExpression(new ConstantExpression("a"))->parse("aaabc");
$result->getString(); // "aaa"
$result->getResults()[0]->getString(); // "a"
连接
PeterVanDommelen\Parser\Expression\Joined\JoinedExpression
new JoinedExpression(ExpressionInterface $inner_expression, ExpressionInterface $seperator_expression, bool $is_lazy = false, int $minimum = 0, int|null $maximum = null)
RepeaterExpression的一种变体,但元素之间有分隔符
$result->getResults();
$result->getSeperators(); //will have a size of count($result->getResults) - 1
非
PeterVanDommelen\Parser\Expression\Not\NotExpression
new NotExpression(ExpressionInterface $inner_expression)
如果内部表达式不匹配,则只匹配单个字符。以下示例将匹配任何字符,但不是 "a" 或 "b"。
new NotExpression(new AlternativeExpression(array(
new ConstantExpression("a"),
new ConstantExpression("b")
))
任何
PeterVanDommelen\Parser\Expression\Any\AnyExpression
new AnyExpression()
匹配任何单个字符。
命名
use PeterVanDommelen\Parser\Expression\Named\NamedExpression
new NamedExpression(string $name)
见下面的语法
语法
编译器支持使用语法,其中条目可以通过NamedExpression引用。
例如,如果我们想找到不包含在匹配括号对内的字符串
$no_opening_brace = new RepeaterExpression(new NotExpression(new AlternativeExpression(array(
new ConstantExpression("(")
))));
$grammar = new Grammar(array(
"expression" => new AlternativeExpression(array(
new ConcatenatedExpression(array(
$no_opening_brace,
new ConstantExpression("("),
new NamedExpression("expression"),
new ConstantExpression(")"),
$no_opening_brace,
)),
$no_opening_brace,
)),
));
$parser = ParserHelper::compileWithGrammar(new NamedExpression("expression"), $grammar);
$result = $parser->parse("ab(c(d)ef)g");
$result->getString(); // "ab(c(d)ef)g"
switch ($result->getKey()) {
case 0:
return $result->getResult()->getPart(0)->getString() . $result->getResult()->getPart(4)->getString(); // "abg"
case 1:
// this branch is not reached
return $result->getResult()->getString(); //
}
性能
忽略编译,你应该期望这个解析器比原生的preg_match慢大约100倍。