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 файл.