railt / lexer
1.3.2
2019-01-18 03:54 UTC
Requires
- php: >=7.1.3
- ext-mbstring: *
- ext-pcre: *
- ext-spl: *
- railt/io: 1.4.*|1.4.x-dev
Requires (Dev)
- phpunit/phpunit: ^6.5
This package is auto-updated.
Last update: 2022-02-01 13:13:35 UTC
README
词法分析器
注意:所有问题和疑问请发送至 https://github.com/railt/railt/issues
注意:测试不能总是正确通过。这可能是因为PPA服务器无法更新gcc和g++导致的。Lexertl构建需要Travis CI内部支持现代编译器。在这种情况下,将显示带有消息“构建错误”的灰色徽章。
为了快速了解其工作原理,只需编写约4行代码
$lexer = Railt\Component\Lexer\Factory::create(['T_WHITESPACE' => '\s+', 'T_DIGIT' => '\d+'], ['T_WHITESPACE']); foreach ($lexer->lex(Railt\Component\Io\File::fromSources('23 42')) as $token) { echo $token . "\n"; }
此示例将读取源文本并返回由其组成的令牌集
T_DIGIT
值为 "23"T_DIGIT
值为 "42"
Factory类的第二个参数是lex方法结果中忽略的令牌名称列表。这就是为什么我们只得到了两个有效的令牌T_DIGIT
。虽然这并不完全正确,但答案中包含一个T_EOI
(输入结束)令牌,也可以通过添加Factory类的第二个参数数组从输出中删除。
...现在让我们尝试了解更多!
词法分析器包含两种类型的运行时
由于同一算法(有状态 vs 无状态)的几个实现之间几乎没有速度差异,因此决定废弃不可变的有状态词法分析器。
use Railt\Component\Lexer\Factory; /** * List of available tokens in format "name => pcre" */ $tokens = ['T_DIGIT' => '\d+', 'T_WHITESPACE' => '\s+']; /** * List of skipped tokens */ $skip = ['T_WHITESPACE']; /** * Options: * 0 - Nothing. * 2 - With PCRE lookahead support. * 4 - With multistate support. */ $flags = Factory::LOOKAHEAD | Factory::MULTISTATE; /** * Create lexer and tokenize sources. */ $lexer = Factory::create($tokens, $skip, $flags);
为了对源文本进行标记化,必须使用->lex(...)
方法,它返回TokenInterface
对象的迭代器。
foreach ($lexer->lex(File::fromSources('23 42')) as $token) { echo $token . "\n"; }
TokenInterface
提供方便的API以获取有关令牌的信息
interface TokenInterface { public function getName(): string; public function getOffset(): int; public function getValue(int $group = 0): ?string; public function getGroups(): iterable; public function getBytes(): int; public function getLength(): int; }
驱动程序
工厂返回可用的实现之一,但是您也可以自己创建它。
基本
原生正则表达式
NativeRegex
实现基于PHP内置的PCRE函数。
use Railt\Component\Lexer\Driver\NativeRegex; use Railt\Component\Io\File; $lexer = new NativeRegex(['T_WHITESPACE' => '\s+', 'T_DIGIT' => '\d+'], ['T_WHITESPACE', 'T_EOI']); foreach ($lexer->lex(File::fromSources('23 42')) as $token) { echo $token->getName() . ' -> ' . $token->getValue() . ' at ' . $token->getOffset() . "\n"; } // Outputs: // T_DIGIT -> 23 at 0 // T_DIGIT -> 42 at 3
Lexertl
基于C++ lexertl库的实验性词法分析器。要使用它,您需要支持Parle扩展。
use Railt\Component\Lexer\Driver\ParleLexer; use Railt\Component\Io\File; $lexer = new ParleLexer(['T_WHITESPACE' => '\s+', 'T_DIGIT' => '\d+'], ['T_WHITESPACE', 'T_EOI']); foreach ($lexer->lex(File::fromSources('23 42')) as $token) { echo $token->getName() . ' -> ' . $token->getValue() . ' at ' . $token->getOffset() . "\n"; } // Outputs: // T_DIGIT -> 23 at 0 // T_DIGIT -> 42 at 3
请注意:库与PCRE正则表达式语法不完全兼容。请参阅官方文档。
多状态
此功能尚未实现。