Compiler construction 使用ANTLR4将算术表达式编译器转换为VHDL(需要更好的方法)
我正在开发一个应用程序,它将为给定的算术表达式生成VHDL代码。为此,我决定使用ANTLR4和JavaFX 到目前为止,我创建了语法。它是为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 ')'
+-*/
操作和整数、浮点数编写的但这并不正确,因为它接受例如这个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;