ANTLR4:算术表达式语法 - 除零检查,关键字检查

问题描述:

我需要此语法的算术表达式帮助。ANTLR4:算术表达式语法 - 除零检查,关键字检查

我想通知用户一些错误消息,如果他试图除以零,或者他使用一些VHDL keywords(目标语言)作为变量名称。

但我是新来的ANTLR,我不能弄清楚如何延长这个语法:

grammar arithmetic; 

@header { 
    package generated; 
} 

stat 
    : Left = VARIABLE Op = ASSIGMENT Right = expr  # Assigment 
    ; 

expr 
    : '(' Exp = expr ')'       # Parens 
    | MINUS Exp = expr        # UnaryMinus 
    | Left = expr Op = (TIMES | DIV) Right = expr # MulDiv 
    | Left = expr Op = (PLUS | MINUS) Right = expr # AddSub 
    | (VARIABLE | CONSTANT)       # Element 
    ; 

ASSIGMENT : '=' ; 
PLUS  : '+' ; 
MINUS  : '-' ; 
TIMES  : '*' ; 
DIV   : '/' ; 
LPAREN  : '(' ; 
RPAREN  : ')' ; 


VARIABLE : (LETTER+|DIGIT+|'_')+ ; 
CONSTANT : INTEGER     ; 

INTEGER  : DIGIT+     ; 


LETTER  : ('a' .. 'z') | ('A' .. 'Z') ; 
DIGIT  : ('0' .. '9') ; 

WS   : [ \r\n\t] + -> skip ; 
+0

用零除在运行时发生,而不是在编译时。 ANTLR系统已经区分了关键字和标识符。你的问题没有意义。 – EJP

+0

那么我正在编译表达式到VHDL代码。所以我需要摆脱VHDL关键字 - “abs”,“access”,“after”,“alias”,“all”,“and”,“architecture”,“array”,“assert”,“attribute” ,“开始”,“块”,“身体”等。上面的关键字只是一个例子,我将编辑问题thnx。 – Samuel

我发现,我在下面的语法已经纠正了许多小问题。

  • 没有EOF标记
  • 只能运行一个语句,因此它扩展到program
  • 的@header事情引起的java grungui不运行
  • _是一个合法的变量名,可能不是你想要什么。
  • '5'是作业的有效左侧。所以5=6是一个有效的赋值语句,可能不是你想要的。

    grammar Arithmetic; 
    program : stat+ EOF; 
    stat 
    : Left = VARIABLE Op = ASSIGMENT Right = expr  # Assigment 
    ; 
    
    expr 
    : '(' Exp = expr ')'       # Parens 
    | MINUS Exp = expr        # UnaryMinus 
    | Left = expr Op = (TIMES | DIV) Right = expr # MulDiv 
    | Left = expr Op = (PLUS | MINUS) Right = expr # AddSub 
    | (VARIABLE | CONSTANT)       # Element 
    ; 
    
    ASSIGMENT : '=' ; 
    PLUS  : '+' ; 
    MINUS  : '-' ; 
    TIMES  : '*' ; 
    DIV   : '/' ; 
    LPAREN  : '(' ; 
    RPAREN  : ')' ; 
    VARIABLE : LETTER+(LETTER|DIGIT|'_')* ; 
    CONSTANT : INTEGER     ; 
    INTEGER  : DIGIT+     ; 
    LETTER  : ('a' .. 'z') | ('A' .. 'Z') ; 
    DIGIT  : ('0' .. '9') ; 
    WS   : [ \r\n\t] + -> skip ; 
    

现在修正了很多文法和“好形式”问题。接下来的问题是如何处理,例如,除以零。

语法是不是地方执行这样的规则。例如,3/0是一个完全合法的数学表达式。它恰好会评估为无穷大,因此在程序中被防范。同样,你应该在代码中处理像这样的特殊情况当您在#MulDiv上下文的右侧等于零时实现您的访问者或侦听器模式时,您应该在该点进行干预。语法不适用于试图实现这样复杂的语义和上下文敏感的规则。

至于如何编程的if声明,我给你在偷看他们的方式我实现了他们:

public override MuValue VisitIfstmt(LISBASICParser.IfstmtContext context) 
    { 
     LISBASICParser.Condition_blockContext[] conditions = context.condition_block(); 
     bool evaluatedBlock = false; 
     foreach (LISBASICParser.Condition_blockContext condition in conditions) 
     { 
      MuValue evaluated = Visit(condition.expr()); 
      if (evaluated.AsBoolean()) 
      { 
       evaluatedBlock = true; 
       Visit(condition.stmt_block()); 
       break; 
      } 
     } 
     if (!evaluatedBlock && context.stmt_block() != null) 
     { 
      Visit(context.stmt_block()); 
     } 
     return MuValue.Void; 
    } 

当然,这可能并没有多大意义,断章取义,但休息保证它的工作。要全面了解这一点,请访问Bart Kiers,以获得语法和实现的绝佳示例。

+0

谢谢你的回答。我正在从GUI的文本字段读取算术表达式,这就是为什么我没有使用EOF。我需要将单个表达式转换为VHDL代码。我想从ANTLR生成的类中分离语法,所以我使用头将其生成为不同的包。我不知道grungui是什么,我的javafx应用程序似乎没有它的工作。你是对的,并且5 = 6。我不希望发生这种情况,谢谢。 – Samuel

+0

在每种情况下,我都可以控制生成的代码中的零分割,而不管它是否是像3/0这样的表达式。但是你是对的,这是合法的表达,所以我不应该在语法上处理它。关于关键字。我的问题是错的,我编辑它。我需要摆脱每个VHDL关键字(有问题的链接)。我正在考虑使用否定符号,不知何故,所有列出的关键字我都不想要。 如果有兴趣,我的丑编译器- https://github.com/SamuelSutaj/diplomovka/tree/testing/Compiler/src – Samuel

+0

@Samuel要处理关键字作为特定的标记,你可以简单地按照专家的建议[in这个SO回答](https://*.com/questions/16419707/antlr4-tokenizing-a-huge-set-of-keywords)来自Sam Harwell。 – TomServo