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

Compiler construction ANTLR4:算术表达式语法-除零检查,关键字检查,compiler-construction,grammar,antlr4,Compiler Construction,Grammar,Antlr4,我需要关于算术表达式语法的帮助 如果用户试图除以零,或者使用某个(目标语言)作为变量名,我想用一些错误消息通知用户 但我是ANTLR的新手,我不知道如何扩展此语法: grammar arithmetic; @header { package generated; } stat : Left = VARIABLE Op = ASSIGMENT Right = expr # Assigment ; expr : '(' Exp = expr

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

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

但我是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 ;

我在下面的语法中发现了许多我已经改正的小问题

  • 无EOF标记
  • 只能运行一条语句,因此将其扩展到
    程序
  • @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;
    }

诚然,这在上下文中可能没有多大意义,但请放心,它是有效的。要全面了解这一点,请访问以获取语法和实现的优秀示例。

零除发生在运行时,而不是编译时。ANTLR系统已经区分了关键字和标识符。你的问题毫无意义。我正在将表达式编译成VHDL代码。因此,我需要去掉VHDL关键字,如“abs”、“access”、“after”、“alias”、“all”、“and”、“architecture”、“array”、“assert”、“attribute”、“begin”、“block”、“body”等。上面的关键字只是示例,我将编辑问题thnx。感谢您的回答。我正在从GUI的textfield中读取算术表达式,这就是为什么我没有使用EOF。我需要将单个表达式转换为VHDL代码。我想将语法和ANTLR生成的类分开,所以我使用header将其生成到不同的包中。我不知道grungui是什么,没有它我的javafx应用程序似乎可以工作。你的u和5=6是对的。“我不希望发生这种情况,谢谢你。@Samuel要将关键字作为特定的标记来处理,你只需遵循Sam Harwell专家的建议即可。