基于SWI-Prolog DCG的编程语言解析器:标识符规则实现咨询
用SWI-Prolog DCG实现多语言简易解析器:标识符处理方案
最近我一直在用SWI-Prolog的确定子句文法(DCG)编写几款编程语言的简易解析器,核心目标很明确——判断输入的字符串或是文件内容是否符合目标语言的语法规范:符合就返回true,不符合就返回false。有意思的是,这些语言几乎都少不了identifier谓词,而且绝大多数语言里标识符的EBNF定义就两种形式,我整理了对应的DCG实现方案,分享给大家:
两种常见的标识符EBNF定义及对应DCG实现
1. 形式一:letter { letter | digit }
这种定义要求标识符必须以字母开头,后续可以跟任意数量(包括0个)的字母或数字。对应的SWI-Prolog DCG实现如下:
% 匹配大小写英文字母 letter --> [C], { code_type(C, alpha) }. % 匹配0-9数字 digit --> [C], { code_type(C, digit) }. % 标识符规则:字母开头,后跟任意字母/数字组合 identifier --> letter, identifier_rest. identifier_rest --> (letter ; digit), identifier_rest. identifier_rest --> []. % 空分支对应{...}的0次匹配情况
可以用这些测试用例验证:
% 合法标识符测试:以字母开头,后跟字母数字 ?- phrase(identifier, "userName123"). true. % 非法标识符测试:以数字开头 ?- phrase(identifier, "123userName"). false.
2. 形式二:( letter | digit ) { letter | digit }
这种定义放宽了开头限制,允许标识符以字母或数字开头,后续同样可以跟任意数量的字母或数字。只需要微调identifier的起始规则即可:
% 标识符规则:字母/数字开头,后跟任意字母/数字组合 identifier --> (letter ; digit), identifier_rest. identifier_rest --> (letter ; digit), identifier_rest. identifier_rest --> [].
测试示例:
% 合法标识符测试:以数字开头 ?- phrase(identifier, "123userName"). true. % 非法标识符测试:包含特殊字符 ?- phrase(identifier, "user-Name"). false.
扩展小技巧
如果需要支持下划线这类常见的标识符允许字符,只需要扩展字符匹配规则即可,比如新增一个id_char谓词:
% 匹配标识符允许的所有字符:字母、数字、下划线 id_char --> letter ; digit ; "_". % 对应形式一的标识符(字母开头) identifier --> letter, identifier_rest. identifier_rest --> id_char, identifier_rest. identifier_rest --> [].
这样就能处理像user_name_456这类带下划线的合法标识符了。
内容的提问来源于stack exchange,提问作者Marcus Hallett
相关产品推荐
相关产品推荐

