Java ANTLR";“投入时无可行的替代方案”;分析SAS代码If Then Else时出错

Java ANTLR";“投入时无可行的替代方案”;分析SAS代码If Then Else时出错,java,parsing,sas,antlr4,parser-generator,Java,Parsing,Sas,Antlr4,Parser Generator,我是ANTLR新手,正在研究一个解析器来解析SAS代码,该代码主要由if-then-else-if语句组成。我创建了以下语法来解析代码,但当我试图使用示例应用程序运行时,Intellij中出现了错误 创建的语法: grammar SASDTModel; parse : if_block+ | score_block ; //Model // : If_block+ // | Score_block // ; if_block : (if_statement|if_in_block)

我是ANTLR新手,正在研究一个解析器来解析SAS代码,该代码主要由if-then-else-if语句组成。我创建了以下语法来解析代码,但当我试图使用示例应用程序运行时,Intellij中出现了错误

创建的语法:

grammar SASDTModel;

parse
 : if_block+
 | score_block
 ;

//Model
// : If_block+
// | Score_block
// ;

if_block
 : (if_statement|if_in_block)
 | else_if_statement+
 | else_statement
 ;

if_statement
 : IF '(' if_condition ')' THEN Identifier'='Value ';'
 | IF Identifier'='Value THEN Identifier'='Value ';'
 ;
else_if_statement
 : ELSEIF '(' if_condition ')' THEN Identifier'='Value ';'
 | ELSEIF Identifier'='Value THEN Identifier'='Value ';'
 ;

if_condition
 : Value ComparisionOperators Identifier ComparisionOperators Value
 | Value ComparisionOperators Value;


else_statement
 : ELSE Identifier'='Value ';'
 ;

if_in_block
 : IF Identifier IN '(' StringArray ')' THEN Identifier'='Value ';'
 ;

score_block
 : Identifier'='Arithmetic_expression ';'
 ;

Arithmetic_expression:
 | ( ArithmeticOperators '(' Value ')' )+
 | ( ArithmeticOperators '(' Value ArithmeticOperators Identifier ')' )+
 ;
WS : ( ' ' | '\t' | '\r' | '\n' )-> channel(HIDDEN);
//WS : [ \t\n\r]+ -> channel(HIDDEN) ;
//WS : (' ' | '\t')+ -> channel(HIDDEN);
//COMMENT    :   '/*' .*? '*/'    -> skip ;
//LINE_COMMENT    :   '*' ~[\r\n]* -> skip ;

ArithmeticOperators:
 | '+'
 | '-'
 | '*'
 | '/'
 | '**'
 ;

ComparisionOperators
 : '=='
 | '<'
 | '>'
 | '<='
 | '>='
 ;

IF: 'IF' | 'if' ;
ELSE: 'ELSE' | 'else' ;
ELSEIF: 'ELSE IF' | 'else if' ;
THEN: 'THEN' | 'then';
IN: 'IN' | 'in';


Value : INT
 | DOUBLE
 | '-'DOUBLE
 | '-'INT
 | Identifier
 |'null';


INT : [0-9];
DOUBLE : INT+ PT INT+
    | PT INT+
    | INT+
    ;
PT  : '.';

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

StringArray : (('\'')(Value)('\''))+; 
语法模型;
作语法分析
:if_块+
|记分块
;
//模型
//:If_块+
//|记分块
// ;
if_块
:(if_语句| if_在_块中)
|else\u if\u语句+
|else_声明
;
if_语句
:如果“(“IF_条件”)”则标识符“=”值“;”
|如果标识符“=”值,则标识符“=”值“;”
;
else\u if\u语句
:ELSEIF'('if_condition'),然后标识符'='Value';'
|ELSEIF标识符“=”值,然后标识符“=”值“;”
;
if_条件
:值比较运算符标识符比较运算符值
|值比较运算符值;
else_声明
:ELSE标识符“=”值“;”
;
如果_在_块中
:如果标识符位于“(“StringArray”)”中,则标识符“=”值“;”
;
记分块
:标识符“=”算术表达式“;”
;
算术表达式:
|(算术运算符“(“值”))+
|(算术运算符“(“值算术运算符标识符”))+
;
WS:(“|”\t“|”\r“|”\n')->频道(隐藏);
//WS:[\t\n\r]+->频道(隐藏);
//WS:(''|'\t')+->通道(隐藏);
//注释:'/*'.'*/'->跳过
//行注释:'*'~[\r\n]*->跳过;
算术运算符:
| '+'
| '-'
| '*'
| '/'
| '**'
;
比较运算符
: '=='
| ''
| '='
;
IF:“IF”|“IF”;
ELSE:“ELSE”|“ELSE”;
ELSEIF:“ELSE IF”|“ELSE IF”;
然后:‘然后’|‘然后’;
IN:'IN'|'IN';
值:INT
|双重的
|“——”双份
|'-'INT
|标识符
|“空”;
国际:[0-9];
双精度:INT+PT INT+
|PT INT+
|INT+
;
PT:';
标识符:('a'..'z'|'a'..'z'|'|'|')('a'..'z'|'a'..'z'|'|'|'0'..'9')*;
StringArray:(“\”)(值)(“\”)+;
输入

if  scored = null then  scored = -0.05;
else if ( 0 <  scored <= 300 ) then scored = -0.5;
else if ( 300 < scored <= 500 ) then scored = -0.4;
else if ( 500 < scored <= 800 ) then scored = -0.8;
else if ( 800 < scored <= 1000 ) then  scored =  0.9;
else if ( scored > 1000 ) then  scored =  1.735409628;
else scored = 0;
如果得分=空,则得分=-0.05;

否则,如果输入的语法不正确,则应使用==而不是=

更新:

此外,尽管INT和DOUBLE的语法应该可以工作,但最好这样表达:

INT : [0-9]+;
DOUBLE : INT PT INT
    | PT INT
    | INT
    ;
否则,300将被标识为DOUBLE,而不是INT

更新2

正如@Raven所评论的:

INT : [0-9]+;
DOUBLE : INT PT INT
    | PT INT
    ;

输入的语法不正确:应使用==而不是=

更新:

此外,尽管INT和DOUBLE的语法应该可以工作,但最好这样表达:

INT : [0-9]+;
DOUBLE : INT PT INT
    | PT INT
    | INT
    ;
否则,300将被标识为DOUBLE,而不是INT

更新2

正如@Raven所评论的:

INT : [0-9]+;
DOUBLE : INT PT INT
    | PT INT
    ;

以下是一些可能导致问题的因素:

  • 通过使
    StringArray:(('\'')(Value)('\'')+;
    成为lexer规则,您将只匹配
    'foo123mu'
    (不带空格的值)。您应该使
    StringArray
    成为解析器规则(然后
    Value
    也应该成为解析器规则)
  • 您的
    else-If
    规则:
    ELSEIF:“else-If”|“else-If”
    非常脆弱:每当
    else
    If
    之间有2个或更多空格时,您的规则将不匹配。您应该删除此规则,并在解析器规则中使用现有的
    else
    If
    规则
  • 规则
    算术运算符
    算术表达式
    匹配临时字符串。Lexer规则决不能匹配空字符串(杠杆可以产生无限量的空字符串标记)
  • 杠杆规则
    算术表达式
    应该是解析器规则:每当杠杆规则用于将其他标记“粘合”到彼此时,您应该将它们“升级”为解析器规则
  • 您的lexer规则命名约定不一致:请使用
    pascalasse
    大写字母
    ,不要同时使用两者
  • 如前所述,
    INT:[0-9];
    应为
    INT:[0-9]+;
    否则
    4
    将标记为
    INT
    42
    DOUBLE
这些只是我在阅读你的问题时看到的一些事情,因此可能有更多的事情是不正确的。我建议你在尝试编写SAS语法之前,首先花时间学习更多的ANTLR。或者,更好的是,尝试为这种语言找到一个现有的(ANTLR)语法,而不是编写自己的语法


这里有一个你可以看一下的现有版本:(不知道它有多准确)

以下是一些可能导致问题的东西:

  • 通过使
    StringArray:(('\'')(Value)('\'')+;
    成为lexer规则,您将只匹配
    'foo123mu'
    (不带空格的值)。您应该使
    StringArray
    成为解析器规则(然后
    Value
    也应该成为解析器规则)
  • 您的
    else-If
    规则:
    ELSEIF:“else-If”|“else-If”
    非常脆弱:每当
    else
    If
    之间有2个或更多空格时,您的规则将不匹配。您应该删除此规则,并在解析器规则中使用现有的
    else
    If
    规则
  • 规则
    算术运算符
    算术表达式
    匹配临时字符串。Lexer规则决不能匹配空字符串(杠杆可以产生无限量的空字符串标记)
  • 杠杆规则
    算术表达式
    应该是解析器规则:每当杠杆规则用于将其他标记“粘合”到彼此时,您应该将它们“升级”为解析器规则
  • 您的lexer规则命名约定不一致:请使用
    pascalasse
    大写字母
    ,不要同时使用两者
  • 如前所述,
    INT:[0-9];
    应为
    INT:[0-9]+;
    否则
    4
    将标记为
    INT
    42
    DOUBLE