2017-08-18 2 views
-1

Ich brauche Hilfe mit dieser Grammatik für arithmetische Ausdrücke.ANTLR4: Grammatik für arithmetischen Ausdruck - Division durch Null-Prüfung, Überprüfung der Schlüsselwörter

Ich möchte den Benutzer mit einer Fehlermeldung benachrichtigen, wenn er versucht, durch Null zu teilen oder wenn er einige VHDL keywords (Zielsprache) als Variablenname verwendet.

Aber ich bin neu in antlr und ich kann nicht herausfinden, wie diese Grammatik erweitern:

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

Division durch Null tritt zur Laufzeit auf, nicht zur Kompilierzeit. Das ANTLR-System unterscheidet bereits zwischen Schlüsselwörtern und Identifikatoren. Deine Frage ergibt keinen Sinn. – EJP

+0

Nun, ich kompiliere Ausdruck in VHDL-Code. Also muss ich VHDL Keywords loswerden wie - "abs", "Zugriff", "nach", "alias", "alle", "und", "Architektur", "Array", "behaupten", "Attribut" , "Beginne", "Block", "Körper" usw. Schlüsselwörter oben waren nur ein Beispiel, ich werde die Frage thnx bearbeiten. – Samuel

Antwort

1

ich zahlreiche kleine Probleme gefunden, die ich in der Grammatik unten korrigiert haben.

  • Keine EOF-Markierung
  • nur eine Anweisung ausgeführt werden kann, so dass es
  • Die @header Sache java grungui verursacht program erweitert läuft nicht
  • _ ein gültiger Variablenname ist, wahrscheinlich nicht, was Sie wollen .
  • '5' ist eine gültige linke Seite der Zuweisung. Also 5=6 ist eine gültige Anweisung, wieder, wahrscheinlich nicht das, was Sie wollen.

    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 ; 
    

nun korrigiert, dass eine Menge lexing und "gute Form" Fragen. Die nächste Frage ist, was man zum Beispiel mit der Division durch Null tun soll.

Die Grammatik ist nicht der Ort, um solche Regeln durchzusetzen. Zum Beispiel ist 3/0 ein vollkommen legaler mathematischer Ausdruck. Es ist einfach so, bis ins Unendliche auszuwerten, und deshalb in einem Programm zu schützen. Ebenso sollten Sie spezielle Fälle wie diesen in Ihrem Code behandeln. Wenn Sie Ihr Besucher- oder Listener-Muster implementieren, wenn die rechte Seite des #MulDiv-Kontexts gleich Null ist, sollten Sie an dieser Stelle eingreifen. Die Grammatik ist kein Ort, um zu versuchen, solch komplizierte semantische und kontextsensitive Regeln zu implementieren.

Was wie eine if Anweisung zu programmieren, werde ich Ihnen einen Blick geben auf sie, wie sie ich implementieren:

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

Zugegeben, das wahrscheinlich nicht viel Sinn aus dem Zusammenhang macht, aber der Rest versicherte, es funktioniert. Um dies in seinem vollen Kontext zu sehen, besuchen Sie bitte Bart Kiers für ein hervorragendes Beispiel für Grammatik und Implementierung.

+0

Vielen Dank für Ihre Antwort. Ich lese arithmetischen Ausdruck aus dem Textfeld von GUI, deshalb habe ich EOF nicht verwendet. Ich muss einen einzelnen Ausdruck in VHDL-Code übersetzen. Ich wollte Grammatik von ANTLR generierten Klassen trennen, also benutzte ich Header, um es zu einem anderen Paket zu generieren. Ich weiß nicht, was Grungui ist, meine Javafx-App scheint ohne sie zu funktionieren. Du hattest Recht mit _ und 5 = 6. Ich will das nicht geschehen, danke. – Samuel

+0

Ich habe in jedem Fall die Kontrolle über die Zero Division im generierten Code, egal ob es sich um einen Ausdruck wie 3/0 handelt oder nicht.Aber du hast recht, es ist legaler Ausdruck, also sollte ich mich nicht in Grammatik darum kümmern. Über Schlüsselwörter. Meine Frage war falsch, ich habe sie bearbeitet. Ich muss jedes VHDL-Schlüsselwort loswerden (Link in Frage). Ich dachte darüber nach, Negationssymbol zu verwenden, irgendwie in Grammatik mit allen aufgelisteten Schlüsselwörtern, die ich nicht will. Bei Interesse, meine hässliche Compiler - https://github.com/SamuelSutaj/diplomovka/tree/testing/Compiler/src – Samuel

+0

@Samuel Um Stichworte als spezifische Token zu behandeln, können Sie einfach folgen Sie dem Rat des Experten [in diese SO Antwort] (https://stackoverflow.com/questions/16419707/antlr4-tokenizing-a-huge-set-of-keywords) von Sam Harwell. – TomServo

Verwandte Themen