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



我需要有关算术表达式语法的帮助。

如果用户尝试除以零或使用某些 VHDL 关键字(目标语言(作为变量名称,我想通知用户一些错误消息。

但是我是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          :   [ rnt] + -> skip ;

我发现了许多小问题,我在下面的语法中纠正了这些问题。

  • 无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          :   [ rnt] + -> 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;
}

当然,这在上下文之外可能没有多大意义,但请放心,它有效。 要在其完整的上下文中看到这一点,请访问 巴特·基尔斯 获取语法和实现的一个很好的例子。

相关内容

  • 没有找到相关文章

最新更新