我需要帮助这个算术表达式的语法。
如果他试图除以零或者使用某些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 :(得分:1)
我发现了许多我在下面的语法中纠正的小问题。
program
_
是一个有效的变量名,可能不是你想要的。 ' 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 ;
现在,纠正了许多lexing和"良好的形式"的问题。接下来的问题是如何处理,例如,除以零。
语法不是强制执行此类规则的地方。例如,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以获得语法和实现的绝佳示例。