You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lark解析器为何将name拆分为单个字符?

问题描述

我尝试解析如下简单文本:

test abc

使用的Lark语法如下:

start: test

test: "test" _WSI name _NL
name: (LETTER | DIGIT | "_")+

%import common.WS_INLINE -> _WSI
%import common.NEWLINE -> _NL
%import common.LETTER
%import common.DIGIT

但打印并pretty_print解析结果时,name被拆分为单个Token:

Tree(Token('RULE', 'start'), [Tree(Token('RULE', 'test'), [Tree(Token('RULE', 'name'), [Token('LETTER', 'a'), Token('LETTER', 'b'), Token('LETTER', 'c')])])])
start
  test
    name
      a
      b
      c

我想知道这是为什么?并希望将name识别为完整字符串而非单个字符。

原因与解决方案

原因

当前语法里的name是语法规则,它由多个基础Token(LETTER/DIGIT/_)组合定义,Lark默认会保留这些基础Token的原始拆分状态,不会自动合并成单个完整字符串。

解决方案

有两种常用方式可以实现将name识别为完整字符串:

  1. 将name定义为词法规则
    在规则名前加!标记,把name转为词法规则。词法规则会在词法分析阶段优先处理,直接将匹配到的连续字符合并成一个完整Token。修改后的语法如下:
start: test

test: "test" _WSI name _NL
!name: (LETTER | DIGIT | "_")+

%import common.WS_INLINE -> _WSI
%import common.NEWLINE -> _NL
%import common.LETTER
%import common.DIGIT
  1. 使用@merge修饰符
    如果不想改动规则类型,可以给name规则添加@merge修饰符,让Lark在解析时自动合并子Token为单个字符串。修改后的语法:
start: test

test: "test" _WSI name _NL
name@merge: (LETTER | DIGIT | "_")+

%import common.WS_INLINE -> _WSI
%import common.NEWLINE -> _NL
%import common.LETTER
%import common.DIGIT

内容的提问来源于stack exchange,提问作者Grrruk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 04:35:57