如何在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
相关产品推荐
相关产品推荐

