Home-Produkte-Testarea-Kontakt-Datenschutz-Aktualisiert: 11-Apr-2009
< Voriger Tag   Nächster Tag >

Samstag, 11. April 2009

Java: Compilerbau mit ANTLR 3 und StringTemplate (1)

ANTLR ist ein Parsergenerator von Terence Parr mit dem sich auf unterschiedliche Weise Compiler erstellen lassen. Eine davon ist die Nutzung von Templates - wie beim Model View Controller werden dabei Modell und Ausgabe voneinander getrennt, so dass nur durch das Hinzufügen eines neuen Templates ein generierter Compiler Programmcode für eine weitere Zielsprache erzeugen kann.

Als einfaches Beispiel wird aus HelloWorld Java-, C- und PHP-Quelltext generiert. Die HelloWorldsprache unterstützt dabei nur den Befehl

helloworld;

Grammatik

Bei ANTLR kann der Lexer und die Grammatik in einer Datei definiert werden. In diesem Fall in HelloWorld.g die Grammatik für eine Sprache, die nur den einen Befehl helloworld; kennt plus die Lexerregel für das überlesen von Whitespace.

Mit options wird festgelegt was ANTLR generieren soll. In diesem Fall einen Parser, der StringTemplate zur Ausgabe nutzt.

program() und helloWorld() sind die extern definierten Templates der einzelnen Zielsprachen. EOF ist in ANTLR eingebaut und steht für das Dateiende. Die Whitespaces werden überlesen, in dem sie in den Kanal 'hidden' geleitet werden.

grammar HelloWorld;

options {output=template;}


program :
    statement EOF -> program(statement={$statement.st})
    ;

statement :
    helloworld ';' -> {$helloworld.st;}
    ;

helloworld :
    'helloworld' -> helloWorld()
    ;

WS  :   (' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;}
    ;

Templates

Die Templates für die Programmiersprachen stehen in einzelnen Dateien mit der Endung '.stg'.

Java.stg

group Java;

program(statement) ::= <<
public class HelloWorld {
    public static void main(String[] args) {
        <statement>
    }
}
>>


helloWorld() ::= <<
System.out.println("Hello World!");
>>

C.stg

group C;

program(statement) ::= <<
#include \<stdio.h\>

int main(int argc, char *argv[]) {
    <statement>

    return 0;
}
>>


helloWorld() ::= <<
printf("Hello World!\\n");
>>

PHP.stg

group PHP;

program(statement) ::= <<
<statement>
>>


helloWorld() ::= <<
echo "Hello World!\\n";
>>

Main

Fehlt noch das Hauptprogramm zum Laden von Template und Eingabe sowie der Initialisierung und Ausführung von Lexer und Parser.

import java.io.*;
import org.antlr.runtime.*;
import org.antlr.stringtemplate.*;
import org.antlr.stringtemplate.language.*;


public class Main {
    public static void main(String[] args)  {
        StringTemplateGroup templates;

        String templateFilename = "";
        String programFilename  = "";


        if(args.length < 2) {
            System.out.println("Main [template] [program]");
            System.exit(0);
        } else {
            templateFilename = args[0];
            programFilename  = args[1];
        }

        try {
            templates = new StringTemplateGroup(new FileReader(templateFilename),
                                                AngleBracketTemplateLexer.class);

            CharStream        input  = new ANTLRFileStream(programFilename);
            HelloWorldLexer   lexer  = new HelloWorldLexer(input);
            CommonTokenStream tokens = new CommonTokenStream(lexer);
            HelloWorldParser  parser = new HelloWorldParser(tokens);

            parser.setTemplateLib(templates);
            RuleReturnScope r = parser.program();

            System.out.println(r.getTemplate().toString());

        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

Compilieren

Zum Compilieren ANTLR-Runtime.jar und StringTemplate.jar in den $CLASSPATH einhängen. Zum Beispiel über Complete ANTLR 3.1.3 jar.

export CLASSPATH=$CLASSPATH:antlr-3.1.3.jar

Und die Grammatik sowie die generierten Dateien compilieren.

java org.antlr.Tool HelloWorld.g
javac Main.java HelloWorldLexer.java HelloWorldParser.java

Ausführen

Zum Ausführen des erstellten Compilers Main mit dem gewünschten Template plus Input starten.

> java Main Java.stg input

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}



> java Main C.stg input

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("Hello World!\n");

    return 0;
}

[Direktlink]

< Voriger Tag   Nächster Tag >

  RSS V0.91

<April 2009 >
  0102030405
06070809101112
13141516171819
20212223242526
27282930   

Home-Produkte-Testarea-Kontakt-Datenschutz-Aktualisiert: 11-Apr-2009
(C) 2000-2018 by Sven Drieling