如何让Leex与Yecc生成的代码支持二进制输入及二进制输出
Leex与Yecc适配UTF-8二进制输入输出的可行方案
1. Leex(.xrl词法规则文件)配置
OTP 18及以上版本直接在规则文件的Definitions段添加编译选项,即可同时支持二进制输入、输出二进制格式的token:
Definitions. % 开启UTF-8编码支持,可直接接收UTF-8二进制输入,按Unicode码点匹配规则 Options = [unicode, {return_binary, true}].
- 配置
unicode选项后,Leex生成的扫描器对外暴露的string/1、token/3等接口可直接传入UTF-8编码的二进制,无需提前转成charlist;规则匹配阶段会自动按Unicode码点识别多字节字符,不会把UTF-8多字节字符拆成单个乱码字节。 - 配置
{return_binary, true}选项后,所有规则匹配捕获的TokenChars默认就是二进制格式,直接封装到token元组传给解析器即可,无需额外转码。
如果使用的OTP版本低于18,没有内置return_binary选项,直接在规则动作里手动转码即可,不需要调整其他配置:
Rules. % 示例:匹配标识符时手动将捕获内容转为二进制 [a-zA-Z_][a-zA-Z0-9_]* : {token, {ident, TokenLine, unicode:characters_to_binary(TokenChars)}}.
2. Yecc(.yrl语法规则文件)配置
Yecc本身不直接处理原始输入文本,只消费Leex输出的token流,不需要添加特殊编译选项,只要遵守两个规则就能保证输出全为二进制格式:
- 语法动作中不要主动将Leex传递过来的二进制值转为charlist,直接透传使用。
- 组装输出结果时,用二进制拼接符
<>代替list拼接符++,硬编码的字符串字面量统一写成二进制格式(比如写<<"function">>不要写"function"),避免混入list类型数据。
规则示例:
% 匹配赋值语句,输出节点值全为二进制 assign -> ident '=' number : {assign, '$1', '$3'}.
上述规则中'$1'是Leex传递的标识符二进制,'$3'是数字对应的二进制/数值类型,最终生成的语法树节点自然全为二进制格式。
注意事项
- 开启
unicode选项后不要在调用扫描器前手动把二进制转成charlist,多一次转码会增加不必要的性能开销。 - 需要匹配中文等非ASCII字符时,直接在正则规则里写对应字符或者Unicode码点范围即可,开启
unicode选项后会自动按UTF-8规则匹配,无需手动处理字节拆分。 - 如果输入可能包含非法UTF-8字节,记得在Leex规则末尾添加兜底错误匹配规则,捕获非法字节做自定义处理,避免扫描器直接抛出异常。
内容的提问来源于stack exchange,提问作者ITChap
相关产品推荐
相关产品推荐

