无法使用带有C#的ANTLR 3解析简单代码

时间:2012-08-04 21:40:22

标签: c# antlr antlr3

鉴于gramar

grammar T;

options
{
    k=4;
  language=CSharp3;     
  TokenLabelType=CommonToken; 
  output=AST;   
  ASTLabelType=CommonTree;  
}

tokens 
{
  LPAREN = '(';
  RPAREN = ')';
  LBRACK = '{';
  RBRACK = '}';
}

fragment
ID  :   ('a'..'z'|'A'..'Z'|'_')('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
WS : (' ' | '\t' | '\n' |'\r' )+ { $channel = Hidden; } ;

public program: CLASSDEF+ EOF!   ;

CLASSDEF: 'class' ID LBRACK
       RBRACK     ;

这会产生词法分析器和解析器,我使用如下

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

namespace compiler
{
  internal class Program2
  {
    public static void Main(string[]arg)
    {
      ANTLRStringStream Input = new ANTLRStringStream(@"class foo 
{ 
}");
      TLexer lex = new TLexer(Input);
      Console.WriteLine("errors:" + lex.NumberOfSyntaxErrors);
      CommonTokenStream tokens = new CommonTokenStream(lex);
      TParser parser = new TParser(tokens);

      var parsed = parser.program();
      Console.WriteLine("errors: " + parser.NumberOfSyntaxErrors);
      CommonTree tree = parsed.Tree;


      Console.WriteLine("type:" + tree.Type);
      Console.WriteLine("text:" + tree.Text);
      Console.WriteLine("children:" +tree.ChildCount);
      Console.WriteLine(tree.ToString());
      Console.WriteLine(tree.ToStringTree());

      Console.ReadKey();
    }
  }
}

运行此代码时,我得到0个lex错误和1个解析错误

结果

errors:0
errors: 1
type:0
text:{
}
children:0
<error: {
}>
<error: {
}>

问题!

  1. 我认为ANTLR应该提供智能错误信息,但我没有发现什么错误

  2. 我是否遗漏了改进错误消息的代码?

1 个答案:

答案 0 :(得分:3)

您使CLASSDEF成为词法规则(换句话说:单个令牌),这是不正确的。当词法分析器偶然发现"class X"之类的输入时,它无法创建CLASSDEF令牌,因为"class""X"之间存在空格(并且不会WS令牌由于CLASSDEF是词法分析器规则,因此无法帮助您。

换句话说:改为使CLASSDEF成为解析器规则(并从fragment移除ID!):

grammar T;

options
{
  language=CSharp3;     
  output=AST; 
}

tokens 
{
  CLASS  = 'class';
  LPAREN = '(';
  RPAREN = ')';
  LBRACK = '{';
  RBRACK = '}';
}

public program
 : class_def+ EOF!
 ;

class_def
 : CLASS ID LBRACK RBRACK
 ;

ID
 : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
 ;

WS
 : (' ' | '\t' | '\n' |'\r' )+ { $channel = Hidden; } 
 ;

现在解析像"class foo { }"这样的输入将产生以下解析:

enter image description here