CC S01E05

Nov. 13, 2013, 8:16 p.m.

Compiler Back-end

О том, как сделать гибкий back-end. Немного о шаблонах, немного о jasmin.

String Templates

test.g

grammar test;

options {
    output = template;
}

input
    : INT -> number(i={$INT.text})
    | sum -> {$sum.st}
    ;

sum
    : i1=INT PLUS i2=INT -> sum(n1={$i1.text}, n2={$i2.text}) 
    ;

INT
    : '0'..'9'+
    ;

PLUS
    : '+'
    ;

test.stg

group test;

sum(n1, n2) ::= <<
+ <n1> <n2>
>>

number(i) ::= <<
<i>
>>

main.java

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

public class Main {
    public static void main(String[] args) throws Exception {
        // load template
        FileReader groupFileR = new FileReader("test.stg");
        StringTemplateGroup templates = new StringTemplateGroup(groupFileR);
        groupFileR.close();

        // create a CharStream that reads from standard input
        ANTLRInputStream input = new ANTLRInputStream(System.in);
        // create a lexer that feeds off of input CharStream
        testLexer lexer = new testLexer(input);
        // create a buffer of tokens pulled from the lexer
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        // create a parser that feeds off the tokens buffer
        testParser parser = new testParser(tokens);
        // use loaded templates
        parser.setTemplateLib(templates);
        // begin parsing at rule r
        testParser.input_return r = parser.input();

        // output stuff
        StringTemplate output = (StringTemplate)r.getTemplate();
        System.out.println(output.toString());
    }
}

Jasmin

hw.j

.class public hw
.super java/lang/Object

;                                                                                                                                                                         
; standard initializer (calls java.lang.Object's initializer)                                                                                                             
;

.method public <init>()V                                                                                                                                                  
    aload_0                                                                                                                                                                
    invokenonvirtual java/lang/Object/<init>()V                                                                                                                            
    return                                                                                                                                                                 
.end method

;                                                                                                                                                                         
; main() - prints out Hello World                                                                                                                                         
;

.method public static main([Ljava/lang/String;)V                                                                                                                          
    .limit stack 2   ; up to two items can be pushed

    ; push System.out onto the stack                                                                                                                                       
    getstatic java/lang/System/out Ljava/io/PrintStream;

    ; push a string onto the stack                                                                                                                                         
    ldc "Hello World!"

    ; call the PrintStream.println() method.                                                                                                                               
    invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V

    ; done                                                                                                                                                                 
    return

.end method

calc2.j

.class public calc2                                                                                                                                                  
.super java/lang/Object

;                                                                                                                                                                         
; standard initializer (calls java.lang.Object's initializer)                                                                                                             
;                                                                                                                                                                         
.method public <init>()V                                                                                                                                                  
    aload_0                                                                                                                                                                
    invokenonvirtual java/lang/Object/<init>()V                                                                                                                            
    return                                                                                                                                                                 
.end method

;                                                                                                                                                                         
; main() - prints out Hello World                                                                                                                                         
;                                                                                                                                                                         
.method public static main([Ljava/lang/String;)V                                                                                                                          
    .limit stack 5
    .limit locals 4

    ; push System.out onto the stack                                                                                                                                       
    getstatic java/lang/System/out Ljava/io/PrintStream;

    ldc2_w 1.0                                                                                                                                                     
    dstore 0

    ldc2_w 2.0
    dstore 2

    dload 2
    dload 0
    ; dmul
    ddiv
    ; dadd
    ; dsub
    ; dneg
    ; invokestatic    java/lang/Math.pow(DD)D

    invokevirtual java/io/PrintStream/println(D)V

    ; done                                                                                                                                                                 
    return                                                                                                                                                                 
.end method

calc3.j

.class public calc3
.super java/lang/Object

;
; standard initializer (calls java.lang.Object's initializer)
;
.method public <init>()V
    aload_0
    invokenonvirtual java/lang/Object/<init>()V
    return
.end method

;
; main() - prints out Hello World
;
.method public static main([Ljava/lang/String;)V
    .limit stack 5
    .limit locals 7

    ; create input reader
    new java/io/InputStreamReader
    dup
    getstatic   java/lang/System/in Ljava/io/InputStream;
    invokenonvirtual    java/io/InputStreamReader.<init>(Ljava/io/InputStream;)V
    astore_1
    new java/io/BufferedReader
    dup
    aload_1
    invokenonvirtual    java/io/BufferedReader.<init>(Ljava/io/Reader;)V
    astore_2

    ; push System.out onto the stack
    getstatic java/lang/System/out Ljava/io/PrintStream;

    ; input
    aload_2
    invokevirtual   java/io/BufferedReader.readLine()Ljava/lang/String;
    invokestatic    java/lang/Double.parseDouble(Ljava/lang/String;)D
    dstore 3

    ; input
    aload_2
    invokevirtual   java/io/BufferedReader.readLine()Ljava/lang/String;
    invokestatic    java/lang/Double.parseDouble(Ljava/lang/String;)D
    dstore 5

    ; operations
    dload 5
    dload 3
    dmul
    ; ddiv
    ; dadd
    ; dsub,
    ; dneg
    ; invokestatic    java/lang/Math.pow(DD)D

    ; print
    invokevirtual java/io/PrintStream/println(D)V

    ; done
    return
.end method

Домашнее задание

Создать полноценный компилятор из своего языка с переменными, арифметическими операциями, вводом и выводом в java class файл.

comments powered by Disqus