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

如何在C#的Antlr Context中为数组添加元素?(PGFPlots场景)

解决Antlr手动构建PGFPlots AST时的空引用问题

你直接实例化AxisContext后,内部的keyValPairs子节点并没有被初始化,调用axis.keyValPairs()会返回null,后续操作自然抛出空引用异常。Antlr生成的语法树节点类不是为手动填充设计的,直接new出来的节点没有完整的内部结构。

下面提供两种可行解决方案:

方案一:直接拼接LaTeX代码(最简单高效)

既然最终目标是生成PGFPlots的LaTeX代码,没必要绕AST,直接根据配置拼接字符串即可:

public string GenerateSourceCode(PgfPlotDefinition plotDefinition)
{
    var notNullProperties = GetNotNullProperties(plotDefinition.AxisDefinition);
    var keyVals = string.Join(", ", notNullProperties.Select(kvp => 
    {
        // 根据值的类型处理格式,比如字符串要加引号
        var valueStr = kvp.Value switch
        {
            string s => $"\"{s}\"",
            int or float => kvp.Value.ToString(),
            _ => kvp.Value.ToString()
        };
        return $"{kvp.Key}={valueStr}";
    }));
    return $"axis[{keyVals}]";
}

这种方式简单直接,避免了AST操作的复杂问题,完全适配你的场景。

方案二:正确构建Antlr语法树节点(如果必须用AST)

如果一定要通过AST来生成代码,需要手动创建所有必要的语法树节点,并正确关联父子关系:

public string GenerateSourceCode(PgfPlotDefinition plotDefinition)
{
    var parser = new PgfPlotsParser(null);
    var axisContext = new PgfPlotsParser.AxisContext(parser, 0);
    
    // 创建keyValPairs节点并关联到axis节点
    var keyValPairsContext = new PgfPlotsParser.KeyValPairsContext(parser, 0);
    axisContext.AddChild(keyValPairsContext);
    
    var notNullProperties = GetNotNullProperties(plotDefinition.AxisDefinition);
    foreach (var kvp in notNullProperties)
    {
        // 创建单个keyValPair节点
        var keyValPairContext = new PgfPlotsParser.KeyValPairContext(parser, 0);
        
        // 创建Key节点并设置文本
        var keyToken = new CommonToken(PgfPlotsLexer.Key, kvp.Key);
        var keyContext = new PgfPlotsParser.KeyContext(parser, 0);
        keyContext.AddChild(keyToken);
        keyValPairContext.AddChild(keyContext);
        
        // 添加等号Token
        var eqToken = new CommonToken(PgfPlotsLexer.EQ, "=");
        keyValPairContext.AddChild(eqToken);
        
        // 创建Value节点并设置文本
        CommonToken valueToken;
        switch (kvp.Value)
        {
            case string s:
                valueToken = new CommonToken(PgfPlotsLexer.STRING, $"\"{s}\"");
                break;
            int i:
                valueToken = new CommonToken(PgfPlotsLexer.INT, i.ToString());
                break;
            float f:
                valueToken = new CommonToken(PgfPlotsLexer.FLOAT, f.ToString());
                break;
            default:
                valueToken = new CommonToken(PgfPlotsLexer.STRING, $"\"{kvp.Value}\"");
                break;
        }
        var valueContext = new PgfPlotsParser.ValueContext(parser, 0);
        valueContext.AddChild(valueToken);
        keyValPairContext.AddChild(valueContext);
        
        // 将keyValPair添加到keyValPairs集合
        keyValPairsContext.AddChild(keyValPairContext);
    }
    
    return axisContext.GetText();
}

这种方式需要处理所有Token和节点的创建,比较繁琐,仅推荐用于有复杂语法生成需求的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 06:50:53