ANTLR Hello World

Installation

  • Installieren von [IntelliJ Community Edition]
    (https://www.jetbrains.com/idea/download/#section=windows) (kostenlos)

  • IntelliJ starten

  • Ein neues Projekt mit New Project - Empty Project starten. In dieser Anleitung gehen wir davon aus, dass das Projekt antlr-hello-world heißt.

  • Settings-Dialog mit Strg+Alt+S öffnen, nach dem antlr Plugin suchen und installieren

    (.Get 1)

  • IntelliJ neu starten und das zuvor angelegte Projekt wieder laden

Erste Grammatik anlegen

  • Neue Datei Hello.g4 anlegen

    (.Get 1)

  • Folgende Grammatik in die neue Datei einfügen:

    grammar Hello;
    greet     : 'hello' ID ;         // Schlüsselwort hello gefolgt von einem Identifier
    ID        : [a-z]+ ;             // Identifier in Kleinbuchstaben
    WS        : [ \t\r\n]+ -> skip ; // Leerzeichen, Tab, Leerzeilen ignorieren
  • Rechte Maustaste auf die Regel greet und Test Rule greet anklicken

    (.Get 1)

  • hello world eingeben und ansehen, wie ANTLR den Text nach der angegebenen Grammatik zerlegt

    (.Get 1)

  • Experimentiere mit folgenden Eingaben (beachte die Fehler, die angezeigt werden)

    • hello
    • helo world

Chat Grammatik

  • Neue Datei Chat.g4 anlegen

    grammar chat;
    
    /*
    * Lexer Rules
    */
    
    fragment A          : ('A'|'a') ;
    fragment S          : ('S'|'s') ;
    fragment Y          : ('Y'|'y') ;
    fragment H          : ('H'|'h') ;
    fragment O          : ('O'|'o') ;
    fragment U          : ('U'|'u') ;
    fragment T          : ('T'|'t') ;
    
    fragment LOWERCASE  : [a-z] ;
    fragment UPPERCASE  : [A-Z] ;
    
    SAYS                : S A Y S ;
    
    SHOUTS              : S H O U T S;
    
    WORD                : (LOWERCASE | UPPERCASE | '_')+ ;
    
    WHITESPACE          : (' ' | '\t');
    
    NEWLINE             : ('\r'? '\n' | '\r')+ ;
    
    /*
    * Parser Rules
    */
    
    chat                : line+ EOF ;
    
    line                : name command message NEWLINE;
    
    message             : (emoticon | mention | WORD | WHITESPACE)+ ;
    
    name                : WORD WHITESPACE;
    
    command             : (SAYS | SHOUTS) ':' WHITESPACE ;
    
    emoticon            : ':' '-'? ')'
                    | ':' '-'? '('
                    ;
    
    mention             : '@' WORD ;
  • Testsätze:

    • tim SAYS: hello world
    • john SHOUTS: hello @michael :-)
  • Antlr Generator konfigurieren

    (.Get 1)

    (.Get 1)

  • Lexer/Parser generieren

    (.Get 1)

    (.Get 1)

Compiler

  • npm init

  • npm install antlr4

  • app.js:

    const antlr4 = require('antlr4');
    const ChatLexer = require('./compiler/chatLexer').chatLexer;
    const ChatParser = require('./compiler/chatParser').chatParser;
    
    const input = 'tim SAYS: hello @world :-)\n';
    
    const chars = new antlr4.InputStream(input);
    const lexer = new ChatLexer(chars);
    const tokens = new antlr4.CommonTokenStream(lexer);
    const parser = new ChatParser(tokens);
    parser.buildParseTrees = true;
    
    const tree = parser.chat();
    
    for(const line of tree.children) {
    if (line.constructor.name !== ChatParser.LineContext.name) {
        // Reached end of program
        break;
    }
    
    const name = line.children[0];
    console.log(`Name: ${name.children[0].getText()}`);
    
    const command = line.children[1];
    console.log(`Command: ${lexer.symbolicNames[command.children[0].getSymbol().type]}`);
    
    const message = line.children[2];
    for(var msg of message.children) {
        switch (msg.constructor.name) {
            case 'TerminalNodeImpl':
                if (msg.getSymbol().type === ChatLexer.WORD) {
                    console.log(`Word: ${msg.getText()}`);
                }
    
                break;
            case ChatParser.MentionContext.name:
                console.log(`Mention: ${msg.children[1].getText()}`);
                break;
            case ChatParser.EmoticonContext.name:
                if (msg.children[msg.children.length - 1].getText() === `)`) {
                    console.log('Happy');
                } else {
                    console.log('Sad');
                }
    
                break;
        }
    }
    }
    
  • node app.js