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

ANTLR C#实现Bencode解析:如何按前令牌值限制字符串长度?

解决ANTLR中Bencode字符串长度依赖的问题

在ANTLR中无法直接修改只读的StopIndex属性来限制当前令牌长度,不过可以通过在Lexer中添加自定义动作手动控制字符读取长度的方式实现Bencode字符串的解析,具体方案如下:

核心思路

Bencode字符串的格式是<正整数>:<对应长度的字符序列>,我们可以在Lexer中先匹配前缀的数字和冒号,然后通过代码获取数字对应的长度,再手动从输入流中读取该长度的字符,最后将这些字符设置为当前令牌的文本,从而生成正确的字符串令牌。

完整语法示例

Lexer语法(BencodeLexer.g4)

lexer grammar BencodeLexer;

// 匹配Bencode字符串前缀(数字+冒号),并手动读取指定长度的字符作为字符串内容
STRING: DIGITS ':' {
    // 提取前缀中的数字部分
    String numStr = getText().substring(0, getText().length() - 1);
    int strLength;
    try {
        strLength = Integer.parseInt(numStr);
        if (strLength < 0) throw new NumberFormatException();
    } catch (NumberFormatException e) {
        // 处理非正整数的非法格式
        throw new LexerNoViableAltException(this);
    }

    // 读取指定长度的字符
    char[] contentChars = new char[strLength];
    for (int i = 0; i < strLength; i++) {
        if (_input.LA(1) == EOF) {
            // 输入流字符不足,抛出异常
            throw new LexerNoViableAltException(this);
        }
        contentChars[i] = (char)_input.LA(1);
        _input.consume(); // 消费当前字符
    }

    // 将令牌文本设置为读取到的字符串内容
    setText(new String(contentChars));
};

// 匹配整数格式:i<数字>e
INT: 'i' DIGITS 'e';

// 列表和字典的起始、结束标记
LIST_START: 'l';
DICT_START: 'd';
END: 'e';

// 辅助片段:匹配数字
fragment DIGITS: [0-9]+;

// 忽略可能的空白(Bencode本身不允许空白,若有需要可保留)
WS: [ \t\n\r]+ -> skip;

Parser语法(BencodeParser.g4)

parser grammar BencodeParser;

options { tokenVocab=BencodeLexer; }

// 顶层规则:Bencode值
bencode: value;

// Bencode支持的四种类型
value: string | integer | list | dict;

string: STRING;
integer: INT;
list: LIST_START value* END;
dict: DICT_START (string value)* END;

关键细节说明

  1. 手动控制输入流消费:通过_input.LA(1)查看当前字符,_input.consume()消费字符,完全替代了ANTLR自动的令牌边界计算,避开了StopIndex只读的限制。
  2. 错误处理:添加了数字格式校验(非正整数、格式错误)和输入流长度不足的异常抛出,保证语法的健壮性。
  3. 令牌文本重写:通过setText()将原本的<数字>:替换为实际的字符串内容,让Parser可以直接使用STRING令牌处理字符串值。

替代方案(Parser层处理)

如果需要在Parser层处理长度验证,可以将前缀数字和冒号作为单独令牌,然后在Parser规则中获取数字值,再从输入流中读取对应长度的内容。但这种方法需要Parser直接操作输入流,代码复杂度更高,不如Lexer层处理简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 20:45:39