Antlr Net如何构建一个简单的语法

Antlr Net如何构建一个简单的语法,antlr,antlr3,Antlr,Antlr3,我试图构建一个简单的语法来解析.Net类型的名称字符串,支持泛型。我承认对任何语言的语法都是全新的。类型字符串可能如下所示 Foo.Bar.Blah(Mom.Dad, Son.Daughter(Frank.Bob), Dog) 基本上,它是递归的。你应该明白这一点 这件事让我完全不知所措。不知道如何开始。我目前构建的实际上不起作用的是: tree grammar XmlTypeName; options { language=CSharp2; } RPAREN : '('

我试图构建一个简单的语法来解析.Net类型的名称字符串,支持泛型。我承认对任何语言的语法都是全新的。类型字符串可能如下所示

Foo.Bar.Blah(Mom.Dad, Son.Daughter(Frank.Bob), Dog)
基本上,它是递归的。你应该明白这一点

这件事让我完全不知所措。不知道如何开始。我目前构建的实际上不起作用的是:

tree grammar XmlTypeName;

options {
    language=CSharp2;
}

RPAREN
  : '('
  ;

LPAREN
  : ')'
  ;

SEP
  : ','
  ;

TYPE  
  : ('a'..'z'|'A'..'Z'|'0'..'9'|'_')+
  ;

prog
  : type;

type
  : TYPE (RPAREN type (SEP type)? LPAREN)? (EOF)?
  ;
这根本不起作用。Antlr3.exe抛出错误,指出树解析器中不允许使用RPARAM和LPARAM。树解析器是我所需要的吗


我想生成一个简单的AST,让我可以向下导航类型。

不,不应该使用树语法。在解析器创建AST之后使用树语法。只需从中删除关键字

还有几句话:

  • 您想在括号内匹配一个或多个逗号分隔的
    类型
    s,但使用了
    类型(SEP类型)
    ,它匹配一个或两个
    类型
    s。您将需要
    类型(SEP类型)*
  • 您没有说明
    类型
    中的
  • 您应该放弃lexer中的文字空格
像这样的事情很可能会奏效:

grammar XmlTypeName;

options {
  language=CSharp2;
}

prog
 : type EOF
 ;

type
 : name (RPAREN type (SEP type)* LPAREN)? 
 ;

name
 : ID (DOT ID)*
 ;

RPAREN
 : '('
 ;

LPAREN
 : ')'
 ;

SEP
 : ','
 ;

DOT
 : '.'
 ;

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

SPACE
 : (' '|'\t')+ {Skip();} // if 'Skip()' doesn't work, try 'skip()'
 ;
然而,上面只是创建了一个简单的令牌列表。如果您想创建一个合适的AST,您需要“告诉”ANTLR哪些节点/令牌是根令牌,哪些要丢弃(如逗号、括号等)

这将创建以下AST:


有关使用ANTLR创建AST的更多信息:

谢谢!大约两个小时后,我设法弄明白我需要拆分ID和“name”解析,其解析方式与类型列表的解析方式大致相同。但那只不过是一棵扁平的树。我还是有点不确定这里的语法到底是什么意思。->是重写,所以它改变了lexer中的标记。。。明白了。。。但是^()的意思是什么?没问题。AST运算符在我在答案末尾发布的链接中进行了解释。此外,它实际上在AST中发出名称“('TYPE','TYPE','TYPE')”。我如何让它从AST中隐藏('s)?或者我甚至应该麻烦吗?我显示它的方式,
'(“
”)“
”,“
从AST中被省略:试试看。同时阅读我在末尾发布的链接:它将解释如何在AST中省略或包含标记。@wasabi,如果您使用我的第二个示例,并且看到括号和逗号,您可能正在使用AntlWorks的解释器:不要,这有点错误。使用AntlWorks的调试器插件tead(显示创建的实际AST,而不仅仅是解析树)。
grammar XmlTypeName;

options {
  output=AST;
  language=CSharp2;
}

tokens {
  TYPE;
  NAME;
}

prog
 : type EOF -> type
 ;

type
 : name (RPAREN type (SEP type)* LPAREN)? -> ^(TYPE name type*)
 ;

name
 : ID (DOT ID)* -> ^(NAME ID+)
 ;

RPAREN
 : '('
 ;

LPAREN
 : ')'
 ;

SEP
 : ','
 ;

DOT
 : '.'
 ;

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

SPACE
 : (' '|'\t')+ {skip();}
 ;