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

新手稿标记语言Lexer开发求助:ANTLR换行匹配异常

解决ANTLR INSIDE_BRACES模式中换行识别的异常问题

问题背景

我正在开发一款手稿专用标记语言,支持无引号自由文本和指令元数据,示例语法如下:

// Origins section demonstrating advanced directives
section origins chapter {
    :title "Origins of Liberal Thought"
    :publish true

    Mill’s influence cannot be overstated. See @Person.bio for his role in
    shaping modern liberal thought. Refer to [[2025-09-23/1a]] and [@section:book.lsd:prologue].

    :sidebar {
        John Stuart Mill is sometimes called the most influential English‑speaking philosopher of the 19th century.
        :notes {
            comment: "This sidebar illustrates the sidebar directive"
        }
    }
    // 更多指令...
}

使用ANTLR设置了三种Lexer模式:Default、INSIDE_BRACES、COLON_MODE,其中INSIDE_BRACES模式出现报错:

line 8:28 extraneous input '\n' expecting {':', RBRACE, NL_INSIDE}

推测是从COLON_MODE退出后,换行无法被正确识别为NL_INSIDE规则,且Lexer规则和Parser规则存在逻辑漏洞。

问题分析

  1. Lexer规则缺陷:
    • 原FREETEXT规则~[ \t\r\n}:] ~[\r\n}]*排除了冒号,导致自由文本中的冒号会被误识别为指令触发符,同时限制了自由文本的合法内容。
    • 规则顺序不合理,EMPTY_LINE在NL_INSIDE之后,可能导致行首空白加换行被NL_INSIDE优先匹配,无法被跳过。
  2. Parser规则缺失:
    • 未在section内容的语法规则中允许NL_INSIDE token,导致换行被视为非法输入。

解决方案

1. 修正INSIDE_BRACES模式的Lexer规则

调整规则顺序和FREETEXT定义,确保自由文本支持冒号、空白行被正确跳过、行首冒号才触发指令:

mode INSIDE_BRACES;

// 行首右大括号:退出当前模式
RBRACE: {getCharPositionInLine() == 0}? '}' -> popMode;

// 空白行(行首仅含空白+换行):跳过
EMPTY_LINE: {getCharPositionInLine() == 0}? [ \t]* [\r\n] -> skip;

// 行首空白:跳过
LEADING_WS: {getCharPositionInLine() == 0}? [ \t]+ -> skip;

// 行首冒号:进入COLON_MODE
COLON_DIRECTIVE: ':' -> pushMode(COLON_MODE), type(COLON);

// 自由文本:允许除换行、右大括号外的所有字符(包括冒号)
FREETEXT: ~[\r\n}]+;

// 保留换行符
NL_INSIDE: '\r'? '\n';

2. 调整Parser规则,允许换行存在

在section内容的语法规则中加入NL_INSIDE,让Parser接受换行作为合法分隔符:

section
    : 'section' ID ID '{' sectionContent '}'
    ;

// 允许指令、自由文本、换行任意组合
sectionContent
    : (directive | freetext | NL_INSIDE)*
    ;

directive
    : COLON ID directiveValue
    ;

// 支持指令的多种值类型(根据需求扩展)
directiveValue
    : STRING
    | BOOLEAN
    | '{' directiveContent '}'
    | arrayValue
    ;

// 指令内部内容同样允许换行
directiveContent
    : (directive | freetext | NL_INSIDE)*
    ;

arrayValue
    : '[' (STRING | ID) (',' (STRING | ID))* ']'
    ;

freetext
    : FREETEXT
    ;

// 基础词法定义
STRING: '"' ~["]* '"';
BOOLEAN: 'true' | 'false';
ID: [a-zA-Z_][a-zA-Z0-9_]*;

3. 确认COLON_MODE的换行退出逻辑

保持COLON_MODE的换行规则不变,确保退出后回到INSIDE_BRACES模式:

mode COLON_MODE;

// 其他指令内容规则...
NL_COLON: '\r'? '\n' -> popMode;

效果说明

  • 自由文本可正常包含冒号、空格等字符,无需引号包裹。
  • 空白行被自动跳过,行首冒号正确触发指令模式。
  • 换行符被Parser合法识别,不再报多余输入错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 07:55:55