为什么输入.TokenStream解析为空

本文关键字:输入 TokenStream 为什么 | 更新日期: 2023-09-27 18:01:25

用鹿角,我正试图为一棵树做一个TreeWalker:

输入:int x = 3

输出AST: ^(VARDEF int x 3)

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

我通过treewalk:

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)); 

结果是输入。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属性时,TokenStream解析为空?

为什么输入.TokenStream解析为空

这是因为在树语法中,生成规则返回没有text属性(或GetText()方法)的TreeRuleReturnScope

如果您想获取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
  ;

和class:

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