Java 变量的ANTLR语法

Java 变量的ANTLR语法,java,antlr,dsl,antlr3,antlrworks,Java,Antlr,Dsl,Antlr3,Antlrworks,看看我的语法 grammar protocol; options { language = Java; output = AST; } //imaginary tokens tokens{ BOOL; CHAR; STRING; } parse : declaration ; declaration : variable ; variable : locals ; locals

看看我的语法

grammar protocol;

options {  
  language = Java; 
  output = AST;
}                     
//imaginary tokens
tokens{ 
BOOL;
CHAR;
STRING;
}
parse
    : declaration
    ;

declaration
    :   variable
    ;
variable
    :   locals
    ;
locals
  :  (bool
  |  char
  |  string)+
  ;
bool
    :'bool' ID -> ^(BOOL ID)
    ;
char
    : 'char' ID -> ^(CHAR ID)
    ;
string  
    :'string' ID -> ^(STRING ID)
    ;

ID  
    : (('a'..'z' | 'A'..'Z'|'_')('a'..'z' | 'A'..'Z'|'0'..'9'|'_'))*
    ;
INT 
    : ('0'..'9')+
    ;
WHITESPACE
    : ('\t' | ' ' | '\r' | '\n' | '\u000C')+ {$channel = HIDDEN;}
    ;  
对于以下输入

bool boolVariable
char charVariable
string stringVariable  
我的语法创建了以下AST

我不能多次声明变量。我不想一次声明同一类型的变量,但我希望这样

bool boolVariable1
bool boolVariable2
bool boolVariable3
string stringVariable1
string stringVariable2
完成此操作后,我希望所有变量都是两种主要类型。共享和本地。在Java中,共享变量(静态)是指所有对象都有一个副本的变量,而局部变量对每个对象都有单独的副本。我希望用户在定义变量集之前明确指定变量的范围。像

locals:
    bool boolVariable1
    bool boolVariable2
    bool boolVariable3
    string stringVariable1
    string stringVariable2
shared:
    bool boolVariable4
    bool boolVariable5
    bool boolVariable6
    string stringVariable3
    string stringVariable4
    char charVariable1
此外,是否有任何方法可以检查用户不能有两个同名变量?像

bool boolVariable
bool boolVariable  
应该会出现某种错误或类似的情况。 有什么想法/帮助吗?
多谢各位

编辑-解决方案

grammar protocol;

options {  
  language = Java; 
  output = AST;
}                     
//imaginary tokens
tokens{ 
BOOL;
CHAR;
STRING;
SBOOL;
SCHAR;
SSTRING;
}
parse
    : declaration
    ;

declaration
    :   variable
    ;
variable
    :   (locals 
    |   shared)*
    ;
locals
  : 'locals:' (bool| char| string)*
  ;
bool
    :'bool' ID -> ^(BOOL ID)
    ;
char
    : 'char' ID -> ^(CHAR ID)
    ;
string  
    :'string' ID -> ^(STRING ID)
    ;
shared
  : 'shared:' (sbool| schar| sstring)*
  ;

sbool
    :'bool' ID -> ^(SBOOL ID)
    ;
schar
    : 'char' ID -> ^(SCHAR ID)
    ;
sstring 
    :'string' ID -> ^(SSTRING ID)
    ;
ID  
    : (('a'..'z' | 'A'..'Z'|'_')('a'..'z' | 'A'..'Z'|'0'..'9'|'_'))*
    ;
INT 
    : ('0'..'9')+
    ;
WHITESPACE
    : ('\t' | ' ' | '\r' | '\n' | '\u000C')+ {$channel = HIDDEN;}
    ;
你可以试试这个:

  locals
      :  bool* char* string*
      ;
它应该允许您声明相同类型的不同变量。 禁止使用相同名称声明不同变量的最好方法(我认为)是使用先前声明的变量保留集合(在Java中)。只需调用Java函数,如

正如Bahdan在中提到的,您需要维护一个已经使用过的名称集合。下面是一个基于更新语法的简单示例(还有一些其他更改,请参见本答案底部的描述)。新规则
var
是使用新成员代码的地方。注意,这里并没有真正的错误处理,只是一个名称检查

grammar protocol;

options {  
  language = Java; 
  output = AST;
}                     
//imaginary tokens
tokens{ 
BOOL;
CHAR;
STRING;
SBOOL;
SCHAR;
SSTRING;
}

@parser::header { 
    import java.util.ArrayList;
}

@members {
    private ArrayList<String> variableNames = new ArrayList<String>();

    private boolean variableDefined(String name){
        return variableNames.contains(name);
    }

    private void defineVariable(String name){
        variableNames.add(name);
    }
}

parse
    : declaration
    ;

declaration
    :   variable
    ;
variable
    :   (locals | shared)*
    ;
locals
    : 'locals:' (bool| char_ | string)*
    ;
bool
    :'bool' var -> ^(BOOL var)
    ;
char_
    : 'char' var -> ^(CHAR var)
    ;
string  
    :'string' var -> ^(STRING var)
    ;
shared
    : 'shared:' (sbool| schar| sstring)*
    ;
sbool
    :'bool' var -> ^(SBOOL var)
    ;
schar
    : 'char' var -> ^(SCHAR var)
    ;
sstring 
    :'string' var -> ^(SSTRING var)
    ;   
var
    : ID 
      {!variableDefined($ID.text)}? //This rule is only satisfied if the variable is new. 
      {defineVariable($ID.text);}  //we made it here, so it's new. Add it for future reference.
    ;    
ID  
    : ('a'..'z' | 'A'..'Z'|'_')('a'..'z' | 'A'..'Z'|'0'..'9'|'_')*
    ;
INT 
    : ('0'..'9')+
    ;
WHITESPACE
    : ('\t' | ' ' | '\r' | '\n' | '\u000C')+ {$channel = HIDDEN;}
    ;
语法协议;
选项{
语言=Java;
输出=AST;
}                     
//假想代币
代币{
布尔;
烧焦
一串
SBOOL;
沙尔;
串;
}
@解析器::头{
导入java.util.ArrayList;
}
@成员{
私有ArrayList variableNames=新ArrayList();
私有布尔变量已定义(字符串名称){
返回variableNames.contains(名称);
}
私有void可定义变量(字符串名称){
变量名称。添加(名称);
}
}
作语法分析
:声明
;
宣言
:变量
;
变量
:(本地人共享)*
;
当地人
:“locals:”(bool | char | string)*
;
布尔
:'bool'变量->^(bool变量)
;
煤焦_
:“char”变量->^(char变量)
;
一串
:“字符串”变量->^(字符串变量)
;
共享
:“共享:”(sbool | schar | sstring)*
;
斯波尔
:“bool”变量->^(SBOOL变量)
;
沙尔
:“char”变量->^(SCHAR变量)
;
串
:'string'变量->^(SSTRING变量)
;   
变量
:ID
{!variableDefined($ID.text)}//仅当变量为新变量时,才满足此规则。
{defineVariable($ID.text);}//我们在这里创建了它,所以它是新的。添加它以供将来参考。
;    
身份证件
:('a''z''a''z''z''a')('a''z''a''z''0''9''9''*
;
国际的
: ('0'..'9')+
;
空白
:('\t'.''.''.'\r'.''.'\n'.'\u000C')+{$channel=HIDDEN;}
;
我可以声明两个变量,比如bool boolVariable bool boolVariable,但是我不能声明两个变量,比如bool boolVariable bool boolVariable12


请参见上文我对
ID
的更改。有一组额外的括号把规则搞乱了。我还将
char
重命名为
char\uu
,以使解析器为我正确编译。

如您所述,将规则更改为,对于我多次声明的每个变量,我都会得到“无可行异常”。局部变量和共享变量呢?此输入工作正常bool boolVariable bool boolVariable char charVariable但此输入不工作bool bool boolVariable1 char char charVariable字符串stringvariable请查看我的编辑。问题解决了,但我还有一个小问题。我可以声明两个变量,比如bool boolVariable bool bool boolVariable,但是我不能声明两个变量,比如bool boolVariable bool boolvariable12这个语法还有一个问题,你必须总是以bool、char和string的顺序定义变量。你可以将你的解决方案作为答案发布并自我接受。谢谢。目前我只能以bool、char和string顺序定义变量。我不希望用户限制,用户可以按任何顺序定义变量。如果我先定义char或string,然后在最后定义bool,我会得到noViableAltException。共享变量和局部变量(关于顺序)的问题也是如此。我还尝试将规则改为“locals:”bool*char\uu*string*,但它甚至都不起作用。@RizwanAbbasi,这很奇怪。这是我的测试输入:“局部变量:字符串a布尔b字符c字符串d布尔e字符f布尔g共享:字符x”它生成以下AST:“局部变量:(字符串a)(布尔b)(字符c)(字符串d)(布尔e)(字符f)(布尔g)共享:(SCHAR x)”。请确保您的
局部变量
共享
规则以
(bool | char | string)*
(顺序不重要)结尾,而不是
bool*char | string*
(顺序很重要)。我尝试了您的输入,它仅适用于共享变量char x的局部变量,它给了我NoviableException。另外,如果我尝试这个命令shared:charx,我在AST中只得到一个,没有更多。我正在使用这种语法(bool | char | string)*@RizwanAbbasi抱歉,我无法重现这个问题。“shared:char x”解析为OK,“shared:char x string y bool z char xx string yy bool zz”解析为OK。您是否可以调试到出现
NoviableException
异常的点?您能否告诉我如何调试?我正在使用ANTLRWorks和eclipse插件。