Compiler construction 使用ANTLR4将算术表达式编译器转换为VHDL(需要更好的方法)

Compiler construction 使用ANTLR4将算术表达式编译器转换为VHDL(需要更好的方法),compiler-construction,javafx-2,vhdl,antlr4,arithmetic-expressions,Compiler Construction,Javafx 2,Vhdl,Antlr4,Arithmetic Expressions,我正在开发一个应用程序,它将为给定的算术表达式生成VHDL代码。为此,我决定使用ANTLR4和JavaFX 到目前为止,我创建了语法。它是为+-*/操作和整数、浮点数编写的但这并不正确,因为它接受例如这个a=b+++c grammar arithmetic; @header { package generated; } stat : VARIABLE ASSIGMENT exp # Assigment ; exp : '(' exp ')'

我正在开发一个应用程序,它将为给定的算术表达式生成VHDL代码。为此,我决定使用ANTLR4和JavaFX

到目前为止,我创建了语法。它是为
+-*/
操作和
整数、浮点数编写的但这并不正确,因为它接受例如这个
a=b+++c

grammar arithmetic;

@header {
    package generated;
}

stat
    :   VARIABLE ASSIGMENT exp      # Assigment
    ;

exp
    :   '(' exp ')'                 # Parens
    |   MINUS exp                   # UnaryMinus
    |   exp (TIMES | DIV)   exp     # MulDiv
    |   exp (PLUS  | MINUS) exp     # AddSub
    |   (VARIABLE | CONSTANT)       # Element
    ;

ASSIGMENT   :   '=' ;
PLUS        :   '+' ;
MINUS       :   '-' ;
TIMES       :   '*' ;
DIV         :   '/' ;
LPAREN      :   '(' ;
RPAREN      :   ')' ;

VARIABLE    :   LETTER                  ;
CONSTANT    :   FLOAT|INTEGER           ;

FLOAT       :   DIGIT+ ('.' DIGIT+)     ;
INTEGER     :   DIGIT+                  ;

LETTER      :   ('a' .. 'z') | ('A' .. 'Z') ;
DIGIT       :   ('0' .. '9')    ;

WS          :   [ \r\n\t] + -> channel (HIDDEN) ;
接下来,用户应该能够修改元素
类型和模式。所以我为它做了UI。我添加了命名常量的选项,并将为每个元素在
位中添加设置
size
的选项

我正在从字符串输入(以丑陋的方式)生成元素表(UI)。我正在将所有元素保存到:

List<Element> elements = new ArrayList<>();
主要问题 我认为使用list保存这些属性不是一个好方法,因为我以后在生成VHDL代码时必须使用它们。我正在考虑如何将它们添加到语法中,然后可能以某种方式将它们包含到输入字符串中(可能将字符串更改为:
a:type:mode=4:type*b:type:mode
),从中生成AST,或者在创建AST后将它们添加到现有AST叶子中

我创建了visitor,它扩展了ANTLR生成的类。现在我用它为发电机提供信息

public class MyVisitor extends arithmeticBaseVisitor<String> {

    private MainGenerator mainGenerator; // generate main.vhdl
    private TestGenerator testGenerator; // generate testbench.vhdl
    private List<Element> elements;

    public MyVisitor (MainGenerator mainGenerator, TestGenerator testGenerator, List<Element> elements) {
        this.mainGenerator = mainGenerator;
        this.testGenerator = testGenerator;
        this.elements = elements;
    }
使用这个生成器类,我正在创建vhdl代码。现在只需要基本布局和信号/常量声明

public class MainGenerator {

    private FileWriter writer;
    private PrintWriter output;

    private List <Element> constants;
    private List <Element> signals;

    MainGenerator() throws IOException {
        this.writer = new FileWriter(new File(".", "main.vhdl"), false);
        this.output = new PrintWriter(writer);

        this.constants = new ArrayList<>();
        this.signals = new ArrayList<>();
    }

    ...

    private void generateEntity() {

        output.println();
        output.println("entity main is");
        output.println("\tport (");
        generateSignals("\t\t");            // generate signal declarations
        output.println("\t);");
        output.println("end main;");
    }

    ...

    private void generateSignals(String tabs) {
        for (int i = 0; i < signals.size(); i++) {
            Element signal = signals.get(i);
            output.print(tabs + "signal " + signal.getIdentifier() + ": " + signal.getMode().toString().toLowerCase() + " " + signal.getType().toString().toLowerCase());
            if( i != signals.size()-1) output.println(";");
            else output.println();
        }
    }
我既没有构建编译器的经验,也没有使用ANTLR的经验,我认为我做得不对。当涉及到更困难的事情,比如声明——将表达式划分为进程时,我将不知所措。(
a=b+c*2
=>用于乘法的代码块
c*2
=>和用于加法的下一个处理块
..+b

这是我的第一个问题——事实上还有更多的问题。我希望不会太长,但我觉得我的项目背景是必要的

谢谢你的建议。如果我的问题有问题,请告诉我,我将尝试编辑它。

...

@Override
public String visitElement(ElementContext ctx) {
    passElementToGenerators();
    return null;
}

@Override
public String visitMulDiv(MulDivContext ctx) {
    visitChildren(ctx);
    //System.out.println("muldiv");
    return null;
}

...

private void passElementToGenerators () {

    Element current = elements.get(0);

    if (current.isConstant()){
        mainGenerator.addConstant(current);
        testbenchGenerator.addConstant(current);

    } else {
        mainGenerator.addSignal(current);
        testbenchGenerator.addSignal(current);
    }

    elements.remove(0);

}

...
public class MainGenerator {

    private FileWriter writer;
    private PrintWriter output;

    private List <Element> constants;
    private List <Element> signals;

    MainGenerator() throws IOException {
        this.writer = new FileWriter(new File(".", "main.vhdl"), false);
        this.output = new PrintWriter(writer);

        this.constants = new ArrayList<>();
        this.signals = new ArrayList<>();
    }

    ...

    private void generateEntity() {

        output.println();
        output.println("entity main is");
        output.println("\tport (");
        generateSignals("\t\t");            // generate signal declarations
        output.println("\t);");
        output.println("end main;");
    }

    ...

    private void generateSignals(String tabs) {
        for (int i = 0; i < signals.size(); i++) {
            Element signal = signals.get(i);
            output.print(tabs + "signal " + signal.getIdentifier() + ": " + signal.getMode().toString().toLowerCase() + " " + signal.getType().toString().toLowerCase());
            if( i != signals.size()-1) output.println(";");
            else output.println();
        }
    }
library IEEE;
use IEEE.std_logic_1164.all

entity main is
    port (
        signal a: out integer;
        signal b: in unsigned;
        signal x: in std_logic_vector
    );
end main;

architecture behavioral of main is

    constant constant: signed := 4.0

begin


end behavioral;