FIRRTLのパーサがANTLRで作られていることが分かったので、これを使えば遊べるような気がしてきた。C++向けにFIRRTLの文法ファイルを変換して、C++で簡易パーサを作って遊んでみる。
まず、ANTLR4のランタイムをダウンロードした。C++用のANTLRランタイムをダウンロードしてコンパイルしておく。s
https://www.antlr.org/download.html
mkdir runtime cd runtime wget https://www.antlr.org/download/antlr4-cpp-runtime-4.7.2-source.zip unzip antlr4-cpp-runtime-4.7.2-source.zip cd runtime cmake . make -j8
FIRRTLのFIRRTL.g4の配置してあるディレクトリに移動し、ANTRLでC++用のクラスファイルを生成した。
antlr4 -Dlanguage=Cpp FIRRTL.g4
生成したFIRRTLParser.cpp
, FIRRTLLexer.cpp
を呼び出すためのラッパーであるmain.cpp
を作っておく。
main.cpp
#include <iostream> #include "antlr4-runtime.h" #include "FIRRTLLexer.h" #include "FIRRTLParser.h" #include "FIRRTLBaseListener.h" using namespace antlr4; int main(int argc, const char* argv[]) { std::ifstream stream; stream.open(argv[1]); ANTLRInputStream input(stream); FIRRTLLexer lexer(&input); CommonTokenStream tokens(&lexer); FIRRTLParser parser(&tokens); FIRRTLParser::CircuitContext* tree = parser.circuit(); std::cout << tree->toStringTree(&parser); return 0; }
ランタイムライブラリと、main.cpp
と、FIRRTLParser.cpp
, FIRRTLLexer.cpp
をまとめてコンパイルして実行ファイルを作成する。
g++ -o firrtl_cpp *.cpp -I./runtime/runtime/src runtime/dist/libantlr4-runtime.a
完成したので、以下の簡単なFIRファイルを読ませて解析させる。
simple_circuit.fir
circuit SimpleCircuit : module SimpleCircuit : output io : {flip in : UInt<32>, out : UInt<32>} io.out <= io.in
./firrtl_cpp simple_test.fir
line 1:23 mismatched input '\n ' expecting {FileInfo, INDENT} (circuit circuit (id SimpleCircuit) : \n module SimpleCircuit : \n output io : { flip in : UInt < 32 > out : UInt < 32 > } \n \n io . out <= io . in \n)
何となく構文解析した結果がダンプできているような気がする。でも、最初のmismatched input
が良く分からないし、もう少し改造して綺麗に表示できないものかね。とりあえずFIRファイルを構文解析できたので良しとする。