PEGKit 是由 Todd Ditchendorf 在 Objective-C 中实现并受 Packrat parsing expression grammar 启发的开源工具包,适用于 iOS 和 OS X。它遵循 MIT 开源许可协议发布。
始终使用 Xcode 工作空间 PEGKit.xcworkspace
,而不是 Xcode 项目。
此项目将 TDTemplateEngine 作为 Git 子模块包含。因此,正确克隆此项目需要添加 -r
参数。
git clone --recursive [email protected]:itod/pegkit.git
PEGKit 受 Terence Parr 的 ANTLR 和 Steven John Metsker 的 《Building Parsers with Java》的极大影响。
PEGKit 框架提供 2 个对 Cocoa 开发者来说有一般意义的基本服务
PKTokenizer
和 PKToken
类实现字符串分词。PEGKit 源代码可在 GitHub 上找到。
关于如何在 iOS 应用中使用 PEGKit 的教程可在 GitHub 上找到。
PEGKit 是同一作者早期框架的重写版,称为 ParseKit。ParseKit 通常被认为是过时的,并且应该使用 PEGKit 进行所有未来的开发。
ParseKit 在运行时生成 动态、非确定性的解析器。ParseKit 生成的解析器表现出差的(指数级的)性能特征——尽管在罕见情况下它们具有一些有趣属性。
PEGKit 在设计时生成用于 确定性(PEG)存储记忆的解析器的 静态 ObjC 源代码,您可以将其编译到您的项目中。PEGKit 生成的解析器表现出好的(线性的)性能特征。
TODO
后缀 !
运算符可用于丢弃不用于计算结果的标记。
示例
addExpr = atom ('+'! atom)*;
atom = Number;
+
标记对于计算匹配加法表达式的结果不是必要的,因此我们可以将其丢弃。
动作是直接嵌入PEGKit语法规则中的小段Objective-C源代码。动作被大括号包围,并放在任何规则引用之后。
在任何一个动作中,都可用一个类型为PKAssembly
的self.assembly
对象作为一个栈(通过PUSH()
和POP()
便利宏)。汇编的栈包含最近解析的标记(PKToken
实例),并且也可用作计算结果时存储工作的位置。
动作在其前面的规则引用匹配后立即执行。因此,最近匹配的标记就在汇编栈的顶部。
示例 1
// matches addition expressions like `1 + 3 + 4`
addExpr = atom plusAtom*;
plusAtom = '+'! atom
{
PUSH_DOUBLE(POP_DOUBLE() + POP_DOUBLE());
};
atom = Number
{
// pop the double value of token on the top of the stack
// and push it back as a double value
PUSH_DOUBLE(POP_DOUBLE());
};
示例 2
// matches or expressions like `foo or bar` or `foo || bar || baz`
orExpr = item (or item {
id rhs = POP();
id lhs = POP();
MyOrNode *orNode = [MyOrNode nodeWithChildren:lhs, rhs];
PUSH(orNode);
})*;
or = 'or'! | '||'!;
item = Word;
@before
- 此处放置设置代码。在开始解析此规则之前执行。@after
- 此处放置清理代码。在解析此规则结束后执行。规则动作放在规则内部——在规则名称之后,但在=
符号之前。
示例
// matches things like `-1` or `---1` or `--------1`
@extension { // this is a "Grammar Action". See below.
@property (nonatomic) BOOL negative;
}
unaryExpr
@before { _negative = NO; }
@after {
double d = POP_DOUBLE();
d = (_negative) ? -d : d;
PUSH_DOUBLE(d);
}
= ('-'! { _negative = !_negative; })+ num;
num = Number;
PEGKit有一个受ANTLR启发的功能,称为“语法动作”。语法动作是执行您想要的操作的一种方法:在各种位置插入您的解析器的.h和.m文件中的任意代码。它们必须放置在您的语法中规则列出之前的最顶部。
以下是所有当前可用的语法动作,以及它们在生成的解析器源代码中的插入位置的描述:
@h
- .h文件顶部@interface
- 在头文件的@interface
部分中@m
- .m文件顶部@extension
- 在.m文件中的私有类扩展@interface MyParser ()
内部@ivars
- 在.m文件中@implementation MyParser {}
内的私有实例变量@implementation
- 在您的解析器的@implementation
部分内部。定义方法的地方。@init
- 在您的解析器的方法内部
@dealloc
- 如果未启用ARC,则在您的解析器的dealloc
方法内部@before
- 此处放置设置代码。在开始解析之前执行。@after
- 此处放置清理代码。在解析结束后执行。(注意,这里列出的@before
和@after
语法动作与可能也放置在每个单独规则中的@before
和@after
是不同的。)