2017-08-18 8 views
-1

私は算術式にこの文法の助けが必要です。ANTLR4:算術式の文法 - ゼロチェックによる除算、キーワードチェック

0で除算しようとすると、または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

0による除算は、コンパイル時ではなく、実行時に発生します。 ANTLRシステムはすでにキーワードと識別子を区別しています。あなたの質問は理にかなっていません。 – EJP

+0

私はVHDLコードに式をコンパイルしています。だから、私は "abs"、 "access"、 "after"、 "alias"、 "all"、 "and"、 "architecture"、 "array"、 "assert"、 "attribute"などのVHDLキーワードを取り除く必要があります。 、 "begin"、 "block"、 "body"などです。上記のキーワードは単なる例であり、thnxを編集します。 – Samuel

答えて

1

私は以下の文法で修正されている多数の小さな問題を発見しました。

  • ないEOFマーカー
  • ステートメントが1つだけので、おそらくあなたが望んでいないものを、Javaのgrunguiが
  • _が有効な変数名で実行しないようにprogram
  • 事が原因@headerにそれを拡張し実行することができます。
  • '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 ; 
    

今では字句と「良い形」の問題の多くを修正します。次の問題は、例えば0による除算のようなことです。

文法は、このような規則を実施するの場所ではなく、ではありません。たとえば、3/0は完全に正当な数学的表現です。それはまさに無限に評価されるので、プログラムでは守られるべきです。同様に、コードにはのような特殊なケースを扱う必要があります。#MurDivコンテキストの右辺がゼロに等しいときに訪問者またはリスナーパターンを実装するときは、その時点で介入する必要があります。文法は、そのような洗練された意味論的および文脈依存の規則を実装しようとする場所ではありません。これはおそらく、文脈の外にあまり意味がありません、

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; 
    } 

は確かに、しかし残り:

if文をプログラムする方法については、私はあなたに彼らは道、私はそれらを実装するに覗いてあげますそれが動作することを保証します。これを完全な文脈で見るには、文法と実装の優れた例については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キーワードを特定のトークンとして扱うには、専門家のアドバイスSam Harwellの「このSOの回答」(https://stackoverflow.com/questions/16419707/antlr4-tokenizing-a-huge-set-of-keywords)を参照してください。 – TomServo