kuria / parser
逐字符字符串解析库
v4.0.0
2018-08-05 22:17 UTC
Requires
- php: >=7.1
Requires (Dev)
- kuria/dev-meta: ^0.4.0
README
逐字符字符串解析库。
内容
功能
- 行号跟踪(可禁用以提高性能)
- 支持 CR、LF 和 CRLF 行结束符
- 详细异常
- 提供许多方法来导航和操作解析器
- 向前/向后预览和查找
- 向前/向后字符消耗
- 状态堆栈
- 字符类型
- 期望
要求
- PHP 7.1+
用法
创建解析器
使用字符串输入创建新的解析器实例。
解析器从第一个字符开始。
<?php use Kuria\Parser\Parser; $input = 'foo bar baz'; $parser = new Parser($input);
解析器属性
解析器有几个公共属性,可用于检查其当前状态
$parser->i
- 当前位置$parser->char
- 当前字符(或NULL
在输入末尾)$parser->lastChar
- 上一个字符(或NULL
在输入开始)$parser->line
- 当前行(如果禁用行跟踪则为NULL
)$parser->end
- 输入结束指示符(在末尾为TRUE
,否则为FALSE
)$parser->vars
- 与当前状态关联的用户定义变量
警告
所有公共属性(除 $parser->vars
之外)都是只读的,并且不得直接由调用代码修改。
使用内置的解析器方法来更改解析器状态。请参阅解析器方法概述。
解析器方法概述
有关更多信息,请参阅相应方法的文档注释。
另请参阅字符类型。
静态方法
getCharType($char): int
- 确定字符类型getCharTypeName($charType): string
- 获取可读字符类型名称
实例方法
getInput(): string
- 获取输入字符串setInput($input): void
- 替换输入字符串(这也会重置解析器)getLength(): int
- 获取输入字符串的长度isTrackingLineNumbers(): bool
- 检查是否启用行号跟踪type(): int
- 获取当前字符的类型is(...$types): bool
- 检查当前字符是否为指定的类型之一atNewline(): bool
- 检查解析器是否在换行序列的开始eat(): ?string
- 跳到下一个字符并返回它(在末尾返回NULL
)spit(): ?string
- 跳到上一个字符并返回它(在开始返回NULL
)shift(): ?string
- 跳到下一个字符并返回它(在末尾返回NULL
)unshift(): ?string
- 跳到上一个字符并返回它(在开始返回NULL
)peek($offset, $absolute = false): ?string
- 获取给定偏移量或绝对位置的字符(不修改状态)seek($offset, $absolute = false): void
- 修改当前位置reset(): void
- 重置状态、变量并回滚到开始位置rewind(): void
- 回到开头eatChar($char): ?string
- 消费特定字符并返回下一个字符tryEatChar(): bool
- 尝试消费特定字符并返回成功状态eatType($type): string
- 消费指定类型的所有字符eatTypes($typeMap): string
- 消费指定类型的所有字符eatWs(): string
- 消费空白字符(如果有)eatUntil($delimiterMap, $skipDelimiter = true, $allowEnd = false): string
- 消费直到指定分隔符的所有字符eatUntilEol($skip = true): string
- 消费直到行尾或输入结束的所有字符eatEol(): string
- 消费行尾序列eatRest(): string
- 消费剩余字符getChunk($start, $end): string
- 获取输入的片段(不影响状态)detectEol(): ?string
- 找到并返回下一个行尾序列(不影响状态)countStates(): int
- 获取存储的状态数量pushState(): void
- 存储当前状态revertState(): void
- 回退到最后存储的状态并弹出它popState(): void
- 弹出最后存储的状态而不回退到它clearStates(): void
- 丢弃所有存储的状态expectEnd(): void
- 确保解析器位于末尾expectNotEnd(): void
- 确保解析器不在末尾expectChar($expectedChar): void
- 确保当前字符与预期匹配expectCharType($expectedType): void
- 确保当前字符是给定的类型
示例 INI 解析器实现
<?php use Kuria\Parser\Parser; /** * INI parser (example) */ class IniParser { /** * Parse an INI string */ public function parse(string $string): array { // create parser $parser = new Parser($string); // prepare variables $data = []; $currentSection = null; // parse while (!$parser->end) { // skip whitespace $parser->eatWs(); if ($parser->end) { break; } // parse the current thing if ($parser->char === '[') { // a section $currentSection = $this->parseSection($parser); } elseif ($parser->char === ';') { // a comment $this->skipComment($parser); } else { // a key=value pair [$key, $value] = $this->parseKeyValue($parser); // add to output if ($currentSection === null) { $data[$key] = $value; } else { $data[$currentSection][$key] = $value; } } } return $data; } /** * Parse a section and return its name */ private function parseSection(Parser $parser): string { // we should be at the [ character now, eat it $parser->eatChar('['); // eat everything until ] $sectionName = $parser->eatUntil(']'); return $sectionName; } /** * Skip a commented-out line */ private function skipComment(Parser $parser): void { // we should be at the ; character now, eat it $parser->eatChar(';'); // eat everything until the end of line $parser->eatUntilEol(); } /** * Parse a key=value pair */ private function parseKeyValue(Parser $parser): array { // we should be at the first character of the key // eat characters until = is found $key = $parser->eatUntil('='); // eat everything until the end of line // that is our value $value = trim($parser->eatUntilEol()); return [$key, $value]; } }
使用解析器
<?php $iniParser = new IniParser(); $iniString = <<<INI ; An example comment name=Foo type=Bar [options] size=150x100 onload= INI; $data = $iniParser->parse($iniString); print_r($data);
输出
Array ( [name] => Foo [type] => Bar [options] => Array ( [size] => 150x100 [onload] => ) )
字符类型
下表列出了默认字符类型。
这些类型作为常量在Parser类
中可用
Parser::C_NONE
- 无字符(NULL)Parser::C_WS
- 空白字符(制表符、换行符、垂直制表符、换页符、回车符和空格)Parser::C_NUM
- 数字字符(《0-9》)Parser::C_STR
- 字符串字符(《a-z》,《A-Z》、《_》和任何8位字符)Parser::C_CTRL
- 控制字符(ASCII 127和ASCII < 32除空白字符外)Parser::C_SPECIAL
-!"#$%&'()*+,-./:;<=>?@[\\]^\`{|}~
自定义字符类型
可以通过扩展基本Parser
类来自定义字符类型。
以下示例将"-
"和".
"从CHAR_SPECIAL
改为CHAR_STR
并继承所有其他内容。
<?php class CustomParser extends Parser { const CHAR_TYPE_MAP = [ '-' => self::C_STR, '.' => self::C_STR, ] + parent::CHAR_TYPE_MAP; // inherit everything else } // usage example $parser = new CustomParser('foo-bar.baz'); var_dump($parser->eatType(CustomParser::C_STR));
输出
string(11) "foo-bar.baz"