ANTLR4将BF翻译成CPP

实验环境

  操作系统:windows 10

  JAVAJDK 1.8

  antlrantlr-4.7.1-complete.jar

  IDE:IntelliJ IDEA 2017.2.7


 实验目的

  实现一种语言的翻译器,将输入的源语言的程序翻译成目标语言程序。

  本次实验中用到了开源的语法分析器——anltr4,由上述的文法设计编译好文法文件,通过antlr处理.g 文件可生成对应的词法分析器和语法分析器的java文件。最终通过java文件的编写实现翻译器。


实验选题

  源语言:BF(Brainfuck)  忽略这个名字吧...

  目标语言:C++

  测试程序:1、HelloWorld程序

       2、斐波那契数列计算

  C++BF语法对比:

    BF是一种极小化的语言。它的表达能力较C++小很多,所以可以将所有的BF程序翻译为C++程序。对于BF语言的语法:传送门;对于C++的语法,大家就比较熟悉了。


文法设计

  设计原则:通过代码嵌套进行分层,以代码作用进行模块划分。


 具体实现

grammar BF;

program
    : statement*
    ;

statement
    : clause  # symbol
    | '[' statement* ']'  # middle
    ;

clause
    : '+'  # plus
    | '-'  # reduce
    | '<'  # less
    | '>'  # great
    | '.'  # point
    | ','  # comma
    ;

WS : [ 	

]+ -> skip ;
BF.g4
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeProperty;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

class translator extends BFBaseListener{

    public ParseTreeProperty<String> BF = new ParseTreeProperty<String>();
    String getBF(ParseTree ctx){
        return BF.get(ctx);
    }
    void setBF(ParseTree ctx, String s){
        BF.put(ctx, s);
    }

    @Override
    public void exitComma(BFParser.CommaContext ctx) {
        setBF(ctx, "    cin >> array[ptr]; 
");
    }

    @Override
    public void exitPoint(BFParser.PointContext ctx) {
        setBF(ctx, "    cout << (char)array[ptr]; 
");
    }

    @Override
    public void exitPlus(BFParser.PlusContext ctx) {
        setBF(ctx, "    array[ptr] = array[ptr] + 1; 
");
    }

    @Override
    public void exitReduce(BFParser.ReduceContext ctx) {
        setBF(ctx, "    array[ptr] = array[ptr] - 1; 
");
    }

    @Override
    public void exitGreat(BFParser.GreatContext ctx) {
        setBF(ctx, "    ++ptr; 
");
    }

    @Override
    public void exitLess(BFParser.LessContext ctx) {
        setBF(ctx, "    --ptr; 
");
    }

    @Override
    public void exitMiddle(BFParser.MiddleContext ctx) {
        // super.exitMiddle(ctx);
        StringBuffer buf  = new StringBuffer();
        buf.append("    while(array[ptr]){ 
");
        for(BFParser.StatementContext vctx : ctx.statement()){
            buf.append("    ");
            buf.append(getBF(vctx));
        }
        buf.append("    }
");
        setBF(ctx, buf.toString());
    }

    @Override
    public void exitSymbol(BFParser.SymbolContext ctx) {
        //super.exitSymbol(ctx);
        setBF(ctx, getBF(ctx.getChild(0)));
    }

    @Override
    public void exitProgram(BFParser.ProgramContext ctx) {
        //super.exitProgram(ctx);
        StringBuffer buf = new StringBuffer();

        for(BFParser.StatementContext vctx : ctx.statement()){
            buf.append(getBF(vctx));
        }
        setBF(ctx, buf.toString());
    }
}

public class BF2cplusplus {
    public static void main(String[] args) throws IOException {
        String path = "F:\IDEA_JAVA\BF2cplusplus\test\fib.bf";
        CharStream inputStream = CharStreams.fromFileName(path);
        BFLexer lexer = new BFLexer(inputStream);
        CommonTokenStream tokenStream = new CommonTokenStream(lexer);
        BFParser parser = new BFParser(tokenStream);
        ParseTreeWalker walker = new ParseTreeWalker();
        translator cpp = new translator();
        ParseTree root = parser.program();
        walker.walk(cpp,root);

        System.setOut(new PrintStream(new BufferedOutputStream(
                new FileOutputStream("F:\IDEA_JAVA\BF2cplusplus\test\fib.cpp")),true));
        System.out.print("#include<bits/stdc++.h>

" +
                "using namespace std;
" +
                "int array[100005];

" +
                "int main(){
" +
                "    int ptr = 0;
");
        System.out.print(cpp.BF.get(root));
        System.out.print("    return 0;
}");
    }
}
/*
注意的是,在一些文法后面用”#”号定义了一个名称,
就会在用于访问生成的抽象语法树AST的访问器中生成该方法,
用于访问当这个规约被满足时候的那个树节点。
 */
BF2cplusplus.java

 效果展示

斐波那契数列程序:

HelloWorld程序:

原文地址:https://www.cnblogs.com/solvit/p/10176435.html