PHP解析器生成器

dev-master 2016-06-20 21:52 UTC

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倍。