# UniAST **Repository Path**: balababa/uni-ast ## Basic Information - **Project Name**: UniAST - **Description**: Define a unified abstract syntax tree (AST)to quickly generate code. - **Primary Language**: C++ - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-02-18 - **Last Updated**: 2025-02-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # What is this? Using this tool, you can simply write the following grammar to generate a simple compiler. ``` module: statement+; statement: assign_stmt; assign_stmt: variable_access Assign expression; variable_access : variable_name ; ... ``` The generated compiler will be able to analysis and generate code for input: ``` a = 1 + 2 b = a + 3 ``` # How to use? ## 1. install java sdk ```bash $ sudo apt install openjdk-17-jdk ``` ## 2. build llvm-project ```bash $ git submodule update --init $ cd thirdparty/LLVM && mkdir build && cd build $ cmake ../llvm \ -DLLVM_ENABLE_PROJECTS="mlir" \ -DLLVM_ENABLE_ASSERTIONS=ON \ -DLLVM_ENABLE_RTTI=ON \ -DCMAKE_BUILD_TYPE=RELEASE $ make -j 32 ``` ## 3. cmake and make ```bash $ mkdir build && cd build $ cmake .. $ make -j 32 ``` ## 4. generate grammar, listener, CMakeLists.txt for TestGrammar ```bash $ ./build/bin/uni-ast ./example/TestGrammar.test -o ./example/test ``` ## 5. build TestGrammar and test it~ ```bash $ cd build $ make -j 32 $ ./bin/TestGrammar_exe ../example/input.txt ``` ## 6. Example output The first part is generated AST: * `<>` are source code content of AST, `` means this node is generate by extra decl after parser grammar, such as `{expr_params = expr_param}` * `root` `assign_stmt`... are predefined AST Node, you can expand this list by add register visitor by using function `REGISTER_FUNCTION` in `BasicVisitor`. The second part is debug info, you can change log info by function `LOGGER.setLogLevel`, the default level is `INFO`, and it is setted in constructor of `BasicVisitor`. The third part is mlir code generated by `BasicVisitor` ``` root(assign_stmt(variable_access(name_access(TEXT ) ) expression<1+2>(expr_params(expr_param<1>(literal<1>(NUMBER<1> ) ) expr_param<2>(literal<2>(NUMBER<2> ) expr_params ) ) ) ) assign_stmt(variable_access(name_access(TEXT ) ) expression(expr_params(expr_param(variable_access(name_access(TEXT ) ) ) expr_param<3>(literal<3>(NUMBER<3> ) expr_params ) ) ) ) ) [2025-02-22 10:34:18] [DEBUG] visit Assign_stmt. [2025-02-22 10:34:18] [DEBUG] visit Variable_access. [2025-02-22 10:34:18] [DEBUG] visit Name_access. [2025-02-22 10:34:18] [DEBUG] visit TEXT. [2025-02-22 10:34:18] [DEBUG] visit Expression. [2025-02-22 10:34:18] [DEBUG] visit Expr_params. [2025-02-22 10:34:18] [DEBUG] visit Expr_param. [2025-02-22 10:34:18] [DEBUG] visit literal. [2025-02-22 10:34:18] [DEBUG] visit NUMBER. [2025-02-22 10:34:18] [DEBUG] visit Expr_param. [2025-02-22 10:34:18] [DEBUG] visit literal. [2025-02-22 10:34:18] [DEBUG] visit NUMBER. [2025-02-22 10:34:18] [DEBUG] visit Op. [2025-02-22 10:34:18] [DEBUG] visit add. [2025-02-22 10:34:18] [DEBUG] visit Assign_stmt. [2025-02-22 10:34:18] [DEBUG] visit Variable_access. [2025-02-22 10:34:18] [DEBUG] visit Name_access. [2025-02-22 10:34:18] [DEBUG] visit TEXT. [2025-02-22 10:34:18] [DEBUG] visit Expression. [2025-02-22 10:34:18] [DEBUG] visit Expr_params. [2025-02-22 10:34:18] [DEBUG] visit Expr_param. [2025-02-22 10:34:18] [DEBUG] visit Variable_access. [2025-02-22 10:34:18] [DEBUG] visit Name_access. [2025-02-22 10:34:18] [DEBUG] visit TEXT. [2025-02-22 10:34:18] [DEBUG] visit Expr_param. [2025-02-22 10:34:18] [DEBUG] visit literal. [2025-02-22 10:34:18] [DEBUG] visit NUMBER. [2025-02-22 10:34:18] [DEBUG] visit Op. [2025-02-22 10:34:18] [DEBUG] visit add. module { func.func private @main() -> i32 { %c1_i32 = arith.constant 1 : i32 %c2_i32 = arith.constant 2 : i32 %0 = arith.addi %c1_i32, %c2_i32 : i32 %alloca = memref.alloca() : memref<1xi32> %c0 = arith.constant 0 : index memref.store %0, %alloca[%c0] : memref<1xi32> %c1 = arith.constant 1 : index %1 = memref.load %alloca[%c1] : memref<1xi32> %c3_i32 = arith.constant 3 : i32 %2 = arith.addi %1, %c3_i32 : i32 %alloca_0 = memref.alloca() : memref<1xi32> %c0_1 = arith.constant 0 : index memref.store %2, %alloca_0[%c0_1] : memref<1xi32> %c0_i32 = arith.constant 0 : i32 return %c0_i32 : i32 } } ``` # More The entire job is divided into two parts: * Generate unified AST (in directory `lib`, `include` and `tools`) * Analysis unified AST and do code generation (in director `runtime`)