/* Source code for RCC-Legacy.
Copyright (C) 2026 Richard Qin
This file is part of RCC.
RCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
RCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with RCC; see the file LICENSE. If not see
. */
#pragma once
/// @file ast.h
/// @brief SysY AST Node Definitions
#include "rcc/sysy_type.h"
#include
#include
#include
namespace rcc {
// Forward declarations of all AST nodes
struct ASTNode;
struct CompUnitNode;
struct FuncDefNode;
struct FuncFParamNode;
struct VarDeclNode;
struct VarDefNode;
struct BlockNode;
struct AssignStmtNode;
struct ExprStmtNode;
struct IfStmtNode;
struct WhileStmtNode;
struct BreakStmtNode;
struct ContinueStmtNode;
struct ReturnStmtNode;
struct IntLiteralNode;
struct FloatLiteralNode;
struct LValNode;
struct FuncCallNode;
struct BinaryExprNode;
struct UnaryExprNode;
struct ImplicitCastNode;
struct InitListNode;
using ASTPtr = std::unique_ptr;
using ASTList = std::vector;
// operators
enum class BinOp {
Add,
Sub,
Mul,
Div,
Mod,
Lt,
Gt,
Le,
Ge,
Eq,
Ne,
And,
Or,
};
enum class UnaryOp { Pos, Neg, Not };
// AST Node Kind
enum class NodeKind {
CompUnit,
FuncDef,
FuncFParam,
VarDecl,
VarDef,
Block,
AssignStmt,
ExprStmt,
IfStmt,
WhileStmt,
BreakStmt,
ContinueStmt,
ReturnStmt,
IntLiteral,
FloatLiteral,
LVal,
FuncCall,
UnaryExpr,
BinaryExpr,
ImplicitCast,
InitList,
};
// AST Node Base Class
struct ASTNode {
NodeKind kind;
BType eval_type = BType::Int;
int lineno = 0;
explicit ASTNode(NodeKind k) : kind(k) {}
virtual ~ASTNode() = default;
// no copy
ASTNode(const ASTNode&) = delete;
ASTNode& operator=(const ASTNode&) = delete;
ASTNode(ASTNode&&) = default;
ASTNode& operator=(ASTNode&&) = default;
};
// Top-level Nodes
struct CompUnitNode : ASTNode {
ASTList decls_and_funcs;
CompUnitNode() : ASTNode(NodeKind::CompUnit) {}
};
struct FuncDefNode : ASTNode {
BType ret_type = BType::Void;
std::string name;
ASTList params; // FuncFParamNode
ASTPtr body; // BlockNode
FuncDefNode() : ASTNode(NodeKind::FuncDef) {}
};
struct FuncFParamNode : ASTNode {
BType btype = BType::Int;
std::string name;
bool is_array = false;
ASTList dims; // first dim is empty, others are ConstExp
FuncFParamNode() : ASTNode(NodeKind::FuncFParam) {}
};
// declarations
struct VarDeclNode : ASTNode {
bool is_const = false;
BType btype = BType::Int;
ASTList defs; // VarDefNode
VarDeclNode() : ASTNode(NodeKind::VarDecl) {}
};
struct VarDefNode : ASTNode {
std::string name;
ASTList dims; // each dim size (ConstExp), scalar has empty dims list
ASTPtr init_val; // InitListNode | Expr | nullptr
VarDefNode() : ASTNode(NodeKind::VarDef) {}
};
struct InitListNode : ASTNode {
ASTList items; // Expr or InitListNode
InitListNode() : ASTNode(NodeKind::InitList) {}
};
// statements
struct BlockNode : ASTNode {
ASTList items; // Decl | Stmt
BlockNode() : ASTNode(NodeKind::Block) {}
};
struct AssignStmtNode : ASTNode {
ASTPtr lval; // LValNode
ASTPtr expr;
AssignStmtNode() : ASTNode(NodeKind::AssignStmt) {}
};
struct ExprStmtNode : ASTNode {
ASTPtr expr; // nullable (empty statement)
ExprStmtNode() : ASTNode(NodeKind::ExprStmt) {}
};
struct IfStmtNode : ASTNode {
ASTPtr cond;
ASTPtr then_stmt;
ASTPtr else_stmt; // nullable
IfStmtNode() : ASTNode(NodeKind::IfStmt) {}
};
struct WhileStmtNode : ASTNode {
ASTPtr cond;
ASTPtr body;
WhileStmtNode() : ASTNode(NodeKind::WhileStmt) {}
};
struct BreakStmtNode : ASTNode {
BreakStmtNode() : ASTNode(NodeKind::BreakStmt) {}
};
struct ContinueStmtNode : ASTNode {
ContinueStmtNode() : ASTNode(NodeKind::ContinueStmt) {}
};
struct ReturnStmtNode : ASTNode {
ASTPtr expr; // nullable for void return
ReturnStmtNode() : ASTNode(NodeKind::ReturnStmt) {}
};
// expressions
struct IntLiteralNode : ASTNode {
int32_t value = 0;
IntLiteralNode() : ASTNode(NodeKind::IntLiteral) { eval_type = BType::Int; }
};
struct FloatLiteralNode : ASTNode {
float value = 0.0f;
FloatLiteralNode() : ASTNode(NodeKind::FloatLiteral) { eval_type = BType::Float; }
};
struct LValNode : ASTNode {
std::string name;
ASTList indices; // index expressions
LValNode() : ASTNode(NodeKind::LVal) {}
};
struct FuncCallNode : ASTNode {
std::string name;
ASTList args;
FuncCallNode() : ASTNode(NodeKind::FuncCall) {}
};
struct BinaryExprNode : ASTNode {
BinOp op;
ASTPtr lhs, rhs;
BinaryExprNode() : ASTNode(NodeKind::BinaryExpr) {}
};
struct UnaryExprNode : ASTNode {
UnaryOp op;
ASTPtr operand;
UnaryExprNode() : ASTNode(NodeKind::UnaryExpr) {}
};
struct ImplicitCastNode : ASTNode {
BType target_type;
ASTPtr operand;
ImplicitCastNode() : ASTNode(NodeKind::ImplicitCast) {}
};
// AST utility functions
/// Print AST (for debugging)
void ast_dump(const ASTNode* node, int indent = 0);
} // namespace rcc