/phpcc

a compiler compiler writen in php

Primary LanguagePHPOtherNOASSERTION

phpcc

phpcc 是一个元编译器,也就是一个用来编写编译器/解释器的库。phpcc 是一个 LALR1 文法解析器,能支持上下文无关文法解析,并实现了大部分 EBNF 功能。

usage

如在样例 sample/json.php 中那样

$tokens = [
    '{','}',',',':','true','false','null','[',']',
    'number'=>'[-]?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?',
    'string'=>'"([^"\\\\]|[\\\\](["\\\\/bfnrt]|u[0-9a-z]{4}))*"',
    'sp'=>'\s+',
];
$rules = [
    'Value'=>[
        [[ ['|','string','number','Object','Array','true','false','null'] ], true],
    ],
    'Object'=>[
        [['{',['?',"string",":","Value",['*',',',"string",":","Value"]],'}'],true],
    ],
    'Array'=>[
        [['[', ['?', 'Value', ['*', ',', 'Value']], ']'], true],
    ],
];

使用 phpcc 需要自己定义词法和语法规则。在 phpcc 中,词法、语法规则都用 php 语法表示,而不是使用类似 yacc 的特殊语法文件。这里用了 php 5.4 中的数组简写方式。

词法规则定义了词,或者说终结符的规则,是一个混合整数下标和字符串下标的数组。使用整数下标(在 php 中,没有写明下标就是自动生成的整数下标)的表示关键词,它的值和名字是一样的。如上面例子中的 '{'、':'、'true'。而用字符串下标定义的则是一个定义了词的正则表达式。如上面例子里的 'string', 'sp'。同时满足多个规则的时候,返回匹配长度最长的结果。长度相同的情况下,优先返回关键词。

语法规则也是一个数组。其中的每一个键就是规则名,或者说非终结符的名字。值是每个规则名对应的规则列表。第一个键表示语法的根规则。规则列表中的每一条规则也是数组。由两个或三个元素组成。第一个是规则的内容,第二个是是否需要回调已经指定回调函数,第三个可选的标记用来表示转换回调时使用的名字。每条规则之间是 或 关系。

在上面的例子里,表示 json 里的数组的 Array 的第一条规则的内容是 ['[', ['?', 'Value', ['*', ',', 'Value']], ']'] 。这条规则有 3 个项,第一个和最后一个是左右方括号。第二个是个复合项。这条规则表示 Array 的由 '[' 开头,然后是可选的内容。内容的第一项是 'Value',然后是 0 或多个 ',', 'Value' ,最后是 ']'。而 Value 的定义则是另一个规则。后面的 true 表示解析时使用默认的回调。如果使用 false 则表示不需要回调。也可以使用 callable 类型的值来指定使用特定的回调。

从这里可以看出,规则内容可以由 词、规则名 或 复合规则组成,也可以为空([]),表示这个规则名可以由空串匹配。

复合规则目前支持 4 种,分别为 '?'、'*'、'+'、'|'。

  • '?' 表示可选,匹配后面的项 0 次或 1 次
  • ''、'+' 表示重复。'' 表示匹配匹配后面的项 0 次或多次,'+' 则是匹配 1 次或多次。
  • '|' 表示或,即后面的项任选一个。

由这些简单的语法规则,就可以用来表达很多复杂的语法定义,用来解析文本了。