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

Lark解析器中无赋值的define语句未被识别,如何解决?

问题分析与解决

你的问题根源在于关键字未被正确识别,以及语法规则的匹配顺序问题:

  1. 关键字识别问题:define字符串符合NAME(CNAME)的定义,Lark的tokenizer默认会将其识别为identifier token,而非define规则所需的字面量关键字。
  2. 规则匹配顺序:expr规则中identifier排在define前面,解析器会优先尝试匹配单个identifier,而非多token的define规则。

解决方法

方法1:显式定义关键字token

在语法中显式定义define、function等关键字,让tokenizer优先识别它们:

import lark

parser = lark.Lark("""
    ?start: statements
    ?statements: ((expr (";" | NEWLINE) | NEWLINE ) )* expr?
    // 调整expr规则顺序,优先匹配关键字相关规则
    ?expr: define | assignment | functioncall | function | identifier | number
    ?functioncall: identifier "(" arguments? ")"
    ?arguments: expr ("," expr)*
    // 使用DEFINE关键字代替字面量
    ?define: DEFINE identifier ("=" expr)?
    ?assignment: identifier "=" expr

    // 使用FUNCTION关键字代替字面量
    ?function: FUNCTION "(" parameters? ")" "->" identifier block
    ?parameters: identifier ("," identifier)*
    ?block: "{" statements "}"

    ?identifier: NAME -> identifier
    ?number: NUMBER -> number

    // 显式定义关键字token
    DEFINE: "define"
    FUNCTION: "function"
    %import common.NEWLINE
    %import common.CNAME -> NAME
    %import common.NUMBER
    %import common.WS_INLINE
    %ignore WS_INLINE
    COMMENT: "/*" /(.|\n)+/x "*/" | "//" /.+/ NEWLINE?
    %ignore COMMENT
""")

方法2:使用Lark的keywords参数

创建Lark实例时直接指定关键字集合,无需修改语法中的字面量:

import lark

parser = lark.Lark("""
    ?start: statements
    ?statements: ((expr (";" | NEWLINE) | NEWLINE ) )* expr?
    // 调整expr规则顺序,优先匹配关键字相关规则
    ?expr: define | assignment | functioncall | function | identifier | number
    ?functioncall: identifier "(" arguments? ")"
    ?arguments: expr ("," expr)*
    ?define: "define" identifier ("=" expr)?
    ?assignment: identifier "=" expr

    ?function: "function" "(" parameters? ")" "->" identifier block
    ?parameters: identifier ("," identifier)*
    ?block: "{" statements "}"

    ?identifier: NAME -> identifier
    ?number: NUMBER -> number

    %import common.NEWLINE
    %import common.CNAME -> NAME
    %import common.NUMBER
    %import common.WS_INLINE
    %ignore WS_INLINE
    COMMENT: "/*" /(.|\n)+/x "*/" | "//" /.+/ NEWLINE?
    %ignore COMMENT
""", keywords={"define", "function"})

关键调整点

  • 关键字优先级:确保define等字符串被识别为关键字,而非普通标识符。
  • 规则顺序:将define、assignment等多token规则放在identifier前面,让解析器优先尝试匹配这些规则。

修改后运行你的测试代码,parser.parse("define b")会正确生成define类型的语法树,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 07:15:27