Lark语法如何实现内联规则?遵循DRY原则避免重复
在Lark中避免语法规则重复的更优实现方式
你不想保留仅用于避免重复的func规则,原语法规则如下:
func: monad | dyad | builtin dyad: "{" dyad* func+ "}" | func+ ":" monad: "(" monad* func+ ")" | func+ "." builtin: NAME
虽然可以将func内联成以下形式,但调试时每次修改都要改动多处,十分繁琐:
dyad: "{" dyad* (monad | dyad | builtin)+ "}" | (monad | dyad | builtin)+ ":" monad: "(" monad* (monad | dyad | builtin)+ ")" | (monad | dyad | builtin)+ "." builtin: NAME
在Lark中有两种更优的实现方式:
方式一:使用语法宏(%define)
通过%define定义纯语法复用片段,既不用保留冗余的func规则,又能实现表达式复用,修改时只需改动一处:
%define func_expr monad | dyad | builtin dyad: "{" dyad* $(func_expr)+ "}" | $(func_expr)+ ":" monad: "(" monad* $(func_expr)+ ")" | $(func_expr)+ "." builtin: NAME
%define定义的是纯语法片段,不会生成对应的语法树节点,完全符合你不想保留func规则的需求。后续修改复用表达式时,仅需调整%define行的内容,所有引用位置会自动同步。
方式二:给临时规则加@ignore装饰器
如果可以接受定义func规则,但不想让它出现在最终语法树中,可给func添加@ignore装饰器,Lark会自动忽略该规则的节点,只展开内容:
func@ignore: monad | dyad | builtin dyad: "{" dyad* func+ "}" | func+ ":" monad: "(" monad* func+ ")" | func+ "." builtin: NAME
这种方式同样能避免内联的繁琐,同时不会让func节点污染解析后的语法结构。
内容的提问来源于stack exchange,提问作者Tom Huntington
相关产品推荐
相关产品推荐

