c# - 为什么 input.TokenStream 解析为 null?

标签 c# c#-2.0 antlr dsl

使用 antlr,我正在尝试为这样的树制作一个 TreeWalker:

输入:int x = 3

输出 AST:^(VARDEF int x 3)

我的解析器工作得很好并且还生成了一个如上所示的 AST,但是每当我想从 AST 解析任何东西时,比如 $variableType.text,在生成的 C# 2.0 TreeWalker 中总是有一个 NullReferenceException。

我的树行者:

tree grammar SGLTreeWalker;
options {
    tokenVocab = SGL;
    language = 'CSharp2'; 
}

[...]

compilationUnit
    :   (statement)+
    ;

statement
    :   variableDefinitionList
    ;

variableDefinitionList
    :   ^(VARDEF variableType variableName expression) { Console.WriteLine($variableType.text); }
    ;
[...]

由规则“variableDefinitionList”生成的有问题的部分如下所示:

Match(input, Token.UP, null);
Console.WriteLine(((variableType1 != null) ? input.TokenStream.ToString(
    input.TreeAdaptor.GetTokenStartIndex(variableType1.Start),
    input.TreeAdaptor.GetTokenStopIndex(variableType1.Start)) : null)); 

事实证明,input.TokenStream 为空,因此抛出 NullReferenceException。我读到如果使用的 TreeNodeStream 没有被缓冲就会发生这种情况,但我使用了 CommonTreeNodeStream 所以我认为它应该被缓冲。这是我用来提交 AST 的代码:

[...]
SGLParser parser = new SGLParser(tStream);
CommonTree t = (CommonTree) parser.compilationUnit().Tree;
Console.WriteLine("; " + t.ToStringTree());
CommonTreeNodeStream  treeStream = new CommonTreeNodeStream(t);
SGLTreeWalker tw = new SGLTreeWalker(treeStream);
tw.compilationUnit();

当我只想获取 $variableType.text 属性时,知道为什么 input.TokenStream 解析为 null 吗?

最佳答案

那是因为在树语法中,产生式规则返回一个 TreeRuleReturnScope,它没有 text 属性(或 GetText() 方法)。

如果您想获取 variableType 规则的文本,您需要显式返回一个 string

演示:


SGL.g

grammar SGL;

options {
  language=CSharp2;
  output=AST;
}

tokens {
  VARDEF;
}

@parser::namespace { SGL }
@lexer::namespace { SGL }

public compilationUnit
  :  statement+ EOF
  ;

statement
  :  variableDefinitionList
  ;

variableDefinitionList
  :   variableType variableName '=' expression 
      -> ^(VARDEF variableType variableName expression)
  ;

variableType
  :  Type
  ;

variableName
  :  ID
  ;

expression
  :  Int
  ;

Type
  :  'int'
  |  'double'
  ;

Int
  :  '0'..'9'+
  ;

ID
  :  ('a'..'z' | 'A'..'Z')+
  ;

Space
  :  ' ' {Skip();}
  ;

SGLTreeWalker.g

tree grammar SGLTreeWalker;

options {
  tokenVocab=SGL;
  language=CSharp2; 
  ASTLabelType=CommonTree;
}

@namespace { SGL }

compilationUnit
  :  statement+
  ;

statement
  :  variableDefinitionList
  ;

variableDefinitionList
  :   ^(VARDEF variableType variableName expression) 
      {Console.WriteLine($variableType.txt);}
  ;

variableType returns [string txt]
  :  Type {$txt = $Type.text;} // note that `Type` is still a normal token! 
  ;

variableName
  :  ID
  ;

expression
  :  Int
  ;

类:

using System;
using Antlr.Runtime;
using Antlr.Runtime.Tree;

namespace SGL
{
  public class Test
  {
    public static void Main (string[] args)
    {
      ANTLRStringStream Input = new ANTLRStringStream("int x = 3");
      SGLLexer Lexer = new SGLLexer(Input);
      CommonTokenStream Tokens = new CommonTokenStream(Lexer);
      SGLParser parser = new SGLParser(Tokens);
      CommonTree t = (CommonTree) parser.compilationUnit().Tree;
      CommonTreeNodeStream  treeStream = new CommonTreeNodeStream(t);
      SGLTreeWalker tw = new SGLTreeWalker(treeStream);
      tw.compilationUnit();
    }
  }
}

产生以下输出:

int

关于c# - 为什么 input.TokenStream 解析为 null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6596808/

相关文章:

java - ANTLR:多个 AST 使用相同的歧义语法?

java - 查看解析文件输出的方法?

java - 从 ANTLR 中的星号/加号规则获取值

c# - LINQ- Max where 条件

c# - EF Core 嵌套的 Linq 选择结果在 N + 1 个 SQL 查询中

c#-2.0 - 对字符串类型的数据表列求和

localhost - MSMQ - 资源不足,无法执行操作

operator-keyword - C# 自定义迭代器实现

c# - 在了解每个 Select/SelectMany 结果的同时转换 Linq 中的序列

c# - 如何对 DataContractSerializer 进行单元测试?