Compare commits

..

1 Commits

Author SHA1 Message Date
Pomelo c0a4de925f irgen实现
2 weeks ago

@ -1,3 +1,4 @@
include_directories(${PROJECT_SOURCE_DIR}/src/antlr4)
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
project(compiler LANGUAGES C CXX) project(compiler LANGUAGES C CXX)

@ -10,69 +10,3 @@ cmake --build build -j "$(nproc)"
# 3.批量检查 # 3.批量检查
find test/test_case -name '*.sy' | sort | while read f; do ./build/bin/compiler --emit-parse-tree "$f" >/dev/null || echo "FAIL $f"; done find test/test_case -name '*.sy' | sort | while read f; do ./build/bin/compiler --emit-parse-tree "$f" >/dev/null || echo "FAIL $f"; done
核心原则:不要在“落后于远端 master”的本地 master 上直接开发和提交。
你以后按这套流程,基本就不会分岔。
**日常标准流程**
1. 每次开始前先同步主干
```bash
git switch master
git fetch origin
git pull --ff-only origin master
```
2. 从最新 master 拉功能分支开发
```bash
git switch -c feature/xxx
```
3. 开发中频繁提交到功能分支
```bash
git add -A
git commit -m "feat: xxx"
```
4. 推送功能分支(不要直接推 master
```bash
git push -u origin feature/xxx
```
5. 合并前,先把你的分支“重放”到最新 master 上
```bash
git fetch origin
git rebase origin/master
```
有冲突就解决后:
```bash
git add -A
git rebase --continue
```
6. 再合并回 master本地或平台 PR 都可)
本地合并推荐:
```bash
git switch master
git pull --ff-only origin master
git merge --ff-only feature/xxx
git push origin master
```
`--ff-only` 的好处是:只允许线性历史,能最大限度避免分叉和脏 merge。
---
**你这次分岔的根因**
你的本地 master 没先追上远端 master远端有新提交然后直接 merge/push导致出现两个方向的提交历史。
---
**三条硬规则(记住就行)**
1. 不在落后状态的 master 上开发。
2. 合并前一定 `fetch + rebase origin/master`
3. 推 master 前先 `pull --ff-only`,失败就先处理,不要强推。
---
如果你愿意,我可以给你一份适配你仓库的 Git alias`gsync`, `gstart`, `gfinish`),以后 3 条命令就走完整流程。

@ -4,8 +4,8 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "SysYLexer.h" #include "antlr4/SysYLexer.h"
#include "SysYParser.h" #include "antlr4/SysYParser.h"
#include "antlr4-runtime.h" #include "antlr4-runtime.h"
struct AntlrResult { struct AntlrResult {

@ -151,16 +151,6 @@ class ConstantInt : public ConstantValue {
int value_{}; int value_{};
}; };
// Argument 表示函数的形式参数,作为 Value 在函数体内直接被引用。
class Argument : public Value {
public:
Argument(std::shared_ptr<Type> ty, std::string name, size_t index);
size_t GetArgIndex() const { return arg_index_; }
private:
size_t arg_index_;
};
// 第一版 Lab2 需要的指令集合。 // 第一版 Lab2 需要的指令集合。
enum class Opcode { enum class Opcode {
Add, Add,
@ -176,7 +166,6 @@ enum class Opcode {
Load, Load,
Store, Store,
Ret, Ret,
Gep, // getelementptr数组元素地址计算
}; };
enum class CmpOp { Eq, Ne, Lt, Le, Gt, Ge }; enum class CmpOp { Eq, Ne, Lt, Le, Gt, Ge };
@ -205,21 +194,6 @@ class GlobalValue : public User {
GlobalValue(std::shared_ptr<Type> ty, std::string name); GlobalValue(std::shared_ptr<Type> ty, std::string name);
}; };
// GlobalVariable 代表一个全局整型变量、常量或数组。
// 标量:打印为 @name = global i32 N。
// 数组:打印为 @name = global [count x i32] zeroinitializer。
class GlobalVariable : public GlobalValue {
public:
GlobalVariable(std::string name, int init_val = 0, int count = 1);
int GetInitValue() const { return init_val_; }
int GetCount() const { return count_; }
bool IsArray() const { return count_ > 1; }
private:
int init_val_;
int count_;
};
class Instruction : public User { class Instruction : public User {
public: public:
Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name = ""); Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name = "");
@ -261,15 +235,7 @@ class ReturnInst : public Instruction {
class AllocaInst : public Instruction { class AllocaInst : public Instruction {
public: public:
// 标量 alloca分配 1 个 i32
AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name); AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name);
// 数组 alloca分配 count 个 i32count 为编译期常量)
AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name, int count);
int GetCount() const { return count_; }
bool IsArray() const { return count_ > 1; }
private:
int count_ = 1;
}; };
class LoadInst : public Instruction { class LoadInst : public Instruction {
@ -309,16 +275,6 @@ class CallInst : public Instruction {
Value* GetArg(size_t index) const; Value* GetArg(size_t index) const;
}; };
// GepInstgetelementptr i32, i32* base, i32 index
// 用于从数组基址 + 线性偏移量计算元素指针。
class GepInst : public Instruction {
public:
GepInst(std::shared_ptr<Type> ptr_ty, Value* base, Value* index,
std::string name);
Value* GetBase() const;
Value* GetIndex() const;
};
// BasicBlock 已纳入 Value 体系,便于后续向更完整 IR 类图靠拢。 // BasicBlock 已纳入 Value 体系,便于后续向更完整 IR 类图靠拢。
// 当前其类型仍使用 void 作为占位,后续可替换为专门的 label type。 // 当前其类型仍使用 void 作为占位,后续可替换为专门的 label type。
class BasicBlock : public Value { class BasicBlock : public Value {
@ -354,8 +310,10 @@ class BasicBlock : public Value {
// Function 当前也采用了最小实现。 // Function 当前也采用了最小实现。
// 需要特别注意:由于项目里还没有单独的 FunctionType // 需要特别注意:由于项目里还没有单独的 FunctionType
// Function 继承自 Value 后,其 type_ 目前只保存”返回类型”, // Function 继承自 Value 后,其 type_ 目前只保存“返回类型”,
// 并不能完整表达”返回类型 + 形参列表”这一整套函数签名。 // 并不能完整表达“返回类型 + 形参列表”这一整套函数签名。
// 这对当前只支持 int main() 的最小 IR 足够,但后续若补普通函数、
// 形参和调用,通常需要引入专门的函数类型表示。
class Function : public Value { class Function : public Value {
public: public:
Function(std::string name, std::shared_ptr<Type> ret_type, Function(std::string name, std::shared_ptr<Type> ret_type,
@ -365,19 +323,12 @@ class Function : public Value {
const BasicBlock* GetEntry() const; const BasicBlock* GetEntry() const;
const std::vector<std::shared_ptr<Type>>& GetParamTypes() const; const std::vector<std::shared_ptr<Type>>& GetParamTypes() const;
size_t GetNumParams() const; size_t GetNumParams() const;
Argument* GetArgument(size_t index) const;
const std::vector<std::unique_ptr<BasicBlock>>& GetBlocks() const; const std::vector<std::unique_ptr<BasicBlock>>& GetBlocks() const;
// 外部函数声明(无函数体,打印为 declare
void SetExternal(bool v) { is_external_ = v; }
bool IsExternal() const { return is_external_; }
private: private:
BasicBlock* entry_ = nullptr; BasicBlock* entry_ = nullptr;
std::vector<std::shared_ptr<Type>> param_types_; std::vector<std::shared_ptr<Type>> param_types_;
std::vector<std::unique_ptr<Argument>> args_;
std::vector<std::unique_ptr<BasicBlock>> blocks_; std::vector<std::unique_ptr<BasicBlock>> blocks_;
bool is_external_ = false;
}; };
class Module { class Module {
@ -385,19 +336,14 @@ class Module {
Module() = default; Module() = default;
Context& GetContext(); Context& GetContext();
const Context& GetContext() const; const Context& GetContext() const;
// 创建函数时当前只显式传入返回类型,尚未接入完整的 FunctionType。
Function* CreateFunction(const std::string& name, Function* CreateFunction(const std::string& name,
std::shared_ptr<Type> ret_type, std::shared_ptr<Type> ret_type,
std::vector<std::shared_ptr<Type>> param_types = {}); std::vector<std::shared_ptr<Type>> param_types = {});
Function* FindFunction(const std::string& name) const;
const std::vector<std::unique_ptr<Function>>& GetFunctions() const; const std::vector<std::unique_ptr<Function>>& GetFunctions() const;
GlobalVariable* CreateGlobalVar(const std::string& name, int init_val = 0, int count = 1);
GlobalVariable* FindGlobalVar(const std::string& name) const;
const std::vector<std::unique_ptr<GlobalVariable>>& GetGlobalVars() const;
private: private:
Context context_; Context context_;
std::vector<std::unique_ptr<GlobalVariable>> global_vars_;
std::vector<std::unique_ptr<Function>> functions_; std::vector<std::unique_ptr<Function>> functions_;
}; };
@ -418,7 +364,6 @@ class IRBuilder {
BinaryInst* CreateMod(Value* lhs, Value* rhs, const std::string& name); BinaryInst* CreateMod(Value* lhs, Value* rhs, const std::string& name);
CmpInst* CreateCmp(CmpOp op, Value* lhs, Value* rhs, const std::string& name); CmpInst* CreateCmp(CmpOp op, Value* lhs, Value* rhs, const std::string& name);
AllocaInst* CreateAllocaI32(const std::string& name); AllocaInst* CreateAllocaI32(const std::string& name);
AllocaInst* CreateAllocaArray(int count, const std::string& name);
LoadInst* CreateLoad(Value* ptr, const std::string& name); LoadInst* CreateLoad(Value* ptr, const std::string& name);
StoreInst* CreateStore(Value* val, Value* ptr); StoreInst* CreateStore(Value* val, Value* ptr);
BranchInst* CreateBr(BasicBlock* target); BranchInst* CreateBr(BasicBlock* target);
@ -426,9 +371,7 @@ class IRBuilder {
BasicBlock* false_bb); BasicBlock* false_bb);
CallInst* CreateCall(Function* callee, const std::vector<Value*>& args, CallInst* CreateCall(Function* callee, const std::vector<Value*>& args,
const std::string& name); const std::string& name);
GepInst* CreateGep(Value* base, Value* index, const std::string& name);
ReturnInst* CreateRet(Value* v); ReturnInst* CreateRet(Value* v);
ReturnInst* CreateRetVoid();
private: private:
Context& ctx_; Context& ctx_;

@ -6,14 +6,18 @@
#include <any> #include <any>
#include <memory> #include <memory>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
#include <unordered_map>
#include "SysYBaseVisitor.h" #include "antlr4/SysYBaseVisitor.h"
#include "SysYParser.h" #include "antlr4/SysYParser.h"
#include "ir/IR.h" #include "ir/IR.h"
#include "sem/Sema.h" #include "sem/Sema.h"
// 前向声明:语义层可能在未来提供更明确的符号类型,用于把符号唯一标识映射到 IR 对象。
struct SemanticVarSymbol;
struct SemanticFuncSymbol;
namespace ir { namespace ir {
class Module; class Module;
class Function; class Function;
@ -23,9 +27,6 @@ class Value;
class IRGenImpl final : public SysYBaseVisitor { class IRGenImpl final : public SysYBaseVisitor {
public: public:
// const 变量名 -> 编译期整数值,用于数组维度折叠。
using ConstEnv = std::unordered_map<std::string, int>;
IRGenImpl(ir::Module& module, const SemanticContext& sema); IRGenImpl(ir::Module& module, const SemanticContext& sema);
std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override; std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override;
@ -33,8 +34,6 @@ class IRGenImpl final : public SysYBaseVisitor {
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override; std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override;
std::any visitBlockItem(SysYParser::BlockItemContext* ctx) override; std::any visitBlockItem(SysYParser::BlockItemContext* ctx) override;
std::any visitDecl(SysYParser::DeclContext* ctx) override; std::any visitDecl(SysYParser::DeclContext* ctx) override;
std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override;
std::any visitConstDef(SysYParser::ConstDefContext* ctx) override;
std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override; std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override;
std::any visitStmt(SysYParser::StmtContext* ctx) override; std::any visitStmt(SysYParser::StmtContext* ctx) override;
std::any visitVarDef(SysYParser::VarDefContext* ctx) override; std::any visitVarDef(SysYParser::VarDefContext* ctx) override;
@ -52,6 +51,10 @@ class IRGenImpl final : public SysYBaseVisitor {
std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override; std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override;
std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override; std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override;
// 辅助接口:数组下标地址计算与全局变量生成
ir::Value* EmitArrayIndex(ir::Value* base_ptr, SysYParser::ExpContext* idx_expr);
void EmitGlobalVariable(SysYParser::VarDefContext* ctx);
private: private:
enum class BlockFlow { enum class BlockFlow {
Continue, Continue,
@ -63,65 +66,33 @@ class IRGenImpl final : public SysYBaseVisitor {
ir::BasicBlock* break_target; ir::BasicBlock* break_target;
}; };
// 判断当前是否处于全局作用域(函数外部)。
bool IsGlobalScope() const { return func_ == nullptr; }
BlockFlow VisitBlockItemResult(SysYParser::BlockItemContext& item); BlockFlow VisitBlockItemResult(SysYParser::BlockItemContext& item);
ir::Value* EvalExpr(SysYParser::ExpContext& expr); ir::Value* EvalExpr(SysYParser::ExpContext& expr);
ir::Value* EvalCond(SysYParser::CondContext& cond); ir::Value* EvalCond(SysYParser::CondContext& cond);
ir::Value* ToBoolValue(ir::Value* v); ir::Value* ToBoolValue(ir::Value* v);
ir::Value* FindInScope(const std::string& name);
std::string NextBlockName(); std::string NextBlockName();
ir::Function* FindFunctionByName(const std::string& name);
// 预声明 SysY runtime 外部函数。 ir::Value* ResolveLValueAddress(SysYParser::LValueContext* ctx);
void DeclareRuntimeFunctions();
// 根据 sema 绑定或 name 查找局部/全局存储槽位(返回 i32* Value
// 如果 lvalue 有下标,还会生成 GEP 指令并返回元素指针。
ir::Value* ResolveStorage(SysYParser::LValueContext* lvalue);
// 编译期常量整数求值(用于数组维度)。
int EvalConstExpr(SysYParser::ConstExpContext* ctx) const;
// 将 ExpContext即 addExp按编译期常量求值用于 funcFParam 维度)。
int EvalExpAsConst(SysYParser::ExpContext* ctx) const;
// 查找变量的数组维度(先查局部,再查全局)。
const std::vector<int>* FindArrayDims(const std::string& name) const;
// 将一组数组下标表达式(已求值为 ir::Value*)折叠为线性偏移 ir::Value*。
ir::Value* ComputeLinearIndex(const std::vector<int>& dims,
const std::vector<SysYParser::ExpContext*>& subs);
// 扁平化 constInitValue 到整数数组(供 const 数组初始化使用)。
void FlattenConstInit(SysYParser::ConstInitValueContext* ctx,
const std::vector<int>& dims, int dim_idx,
std::vector<int>& out, int& pos);
// 扁平化 initValue 到 ir::Value* 数组(供普通数组初始化使用)。
void FlattenInit(SysYParser::InitValueContext* ctx,
const std::vector<int>& dims, int dim_idx,
std::vector<ir::Value*>& out, int& pos);
ir::AllocaInst* CreateEntryAllocaI32(const std::string& name);
ir::AllocaInst* CreateEntryAllocaArray(int count, const std::string& name);
ir::Module& module_; ir::Module& module_;
const SemanticContext& sema_; const SemanticContext& sema_;
ir::Function* func_; ir::Function* func_;
ir::IRBuilder builder_; ir::IRBuilder builder_;
// 声明 -> 存储槽位(局部 alloca 或全局变量,均为 i32*)。 bool in_function_ = false;
// 当前函数的参数对应的栈槽位(在函数入口处为每个形参分配的 alloca
std::vector<ir::Value*> param_slots_;
// 将 Sema 提供的变量符号映射到对应的存储槽位(避免仅按名字查找)
std::unordered_map<const SemanticVarSymbol*, ir::Value*> symbol_storage_map_;
// 将 Sema 提供的函数符号映射到已创建的 IR 函数对象
std::unordered_map<const SemanticFuncSymbol*, ir::Function*> func_symbol_map_;
// 作用域栈:每个作用域维护一个从名称到存储槽位的映射
std::vector<std::unordered_map<std::string, ir::Value*>> scope_storage_;
// 名称绑定由 Sema 负责IRGen 只维护“声明 -> 存储槽位”的代码生成状态。
std::unordered_map<SysYParser::VarDefContext*, ir::Value*> storage_map_; std::unordered_map<SysYParser::VarDefContext*, ir::Value*> storage_map_;
// 名称 -> 槽位参数、const 变量等不经 sema binding 的后备查找)。 // 保留按名字的映射以兼容现有代码路径,但优先使用 symbol_storage_map_
std::unordered_map<std::string, ir::Value*> named_storage_; std::unordered_map<std::string, ir::Value*> named_storage_;
// 全局变量名 -> GlobalVariable*(跨函数持久)。
std::unordered_map<std::string, ir::Value*> global_storage_;
// 编译期 const 整数环境(全局 + 当前函数)。
ConstEnv const_env_;
// 数组维度信息:全局数组(跨函数持久)。
std::unordered_map<std::string, std::vector<int>> global_array_dims_;
// 数组维度信息:局部数组/参数(每函数清空)。
std::unordered_map<std::string, std::vector<int>> local_array_dims_;
// 逻辑与/或短路求值复用的函数级临时槽位,避免循环中动态 alloca 导致栈膨胀。
ir::Value* short_circuit_slot_ = nullptr;
std::vector<LoopTargets> loop_stack_; std::vector<LoopTargets> loop_stack_;
}; };

@ -1,50 +1,67 @@
#ifndef SEMANTIC_ANALYSIS_H #ifndef SEMANTIC_ANALYSIS_H
#define SEMANTIC_ANALYSIS_H #define SEMANTIC_ANALYSIS_H
#include <any> #include "SymbolTable.h"
#include <memory> #include "antlr4/SysYBaseVisitor.h"
#include <sstream> #include "antlr4/SysYParser.h"
#include <vector>
#include <string> #include <string>
#include <sstream>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <any>
#include <memory>
#include "SymbolTable.h"
#include "SysYBaseVisitor.h"
#include "SysYParser.h"
// 错误信息结构体
struct ErrorMsg { struct ErrorMsg {
std::string msg; std::string msg;
int line; int line;
int column; int column;
ErrorMsg(std::string m, int l, int c) : msg(std::move(m)), line(l), column(c) {} ErrorMsg(std::string m, int l, int c) : msg(std::move(m)), line(l), column(c) {}
}; };
// 前向声明
namespace antlr4 {
class ParserRuleContext;
namespace tree {
class ParseTree;
}
}
// 语义/IR生成上下文核心类
class IRGenContext { class IRGenContext {
public: public:
// 错误管理
void RecordError(const ErrorMsg& err) { errors_.push_back(err); } void RecordError(const ErrorMsg& err) { errors_.push_back(err); }
const std::vector<ErrorMsg>& GetErrors() const { return errors_; } const std::vector<ErrorMsg>& GetErrors() const { return errors_; }
bool HasError() const { return !errors_.empty(); } bool HasError() const { return !errors_.empty(); }
void ClearErrors() { errors_.clear(); } void ClearErrors() { errors_.clear(); }
void SetType(void* ctx, SymbolType type) { node_type_map_[ctx] = type; } // 类型绑定/查询 - 使用 void* 以兼容测试代码
void SetType(void* ctx, SymbolType type) {
node_type_map_[ctx] = type;
}
SymbolType GetType(void* ctx) const { SymbolType GetType(void* ctx) const {
auto it = node_type_map_.find(ctx); auto it = node_type_map_.find(ctx);
return it == node_type_map_.end() ? SymbolType::TYPE_UNKNOWN : it->second; return it == node_type_map_.end() ? SymbolType::TYPE_UNKNOWN : it->second;
} }
void SetConstVal(void* ctx, const std::any& val) { const_val_map_[ctx] = val; } // 常量值绑定/查询 - 使用 void* 以兼容测试代码
void SetConstVal(void* ctx, const std::any& val) {
const_val_map_[ctx] = val;
}
std::any GetConstVal(void* ctx) const { std::any GetConstVal(void* ctx) const {
auto it = const_val_map_.find(ctx); auto it = const_val_map_.find(ctx);
return it == const_val_map_.end() ? std::any() : it->second; return it == const_val_map_.end() ? std::any() : it->second;
} }
// 循环状态管理
void EnterLoop() { sym_table_.EnterLoop(); } void EnterLoop() { sym_table_.EnterLoop(); }
void ExitLoop() { sym_table_.ExitLoop(); } void ExitLoop() { sym_table_.ExitLoop(); }
bool InLoop() const { return sym_table_.InLoop(); } bool InLoop() const { return sym_table_.InLoop(); }
// 类型判断工具函数
bool IsIntType(const std::any& val) const { bool IsIntType(const std::any& val) const {
return val.type() == typeid(long) || val.type() == typeid(int); return val.type() == typeid(long) || val.type() == typeid(int);
} }
@ -53,12 +70,20 @@ class IRGenContext {
return val.type() == typeid(double) || val.type() == typeid(float); return val.type() == typeid(double) || val.type() == typeid(float);
} }
SymbolType GetCurrentFuncReturnType() const { return current_func_ret_type_; } // 当前函数返回类型
void SetCurrentFuncReturnType(SymbolType type) { current_func_ret_type_ = type; } SymbolType GetCurrentFuncReturnType() const {
return current_func_ret_type_;
}
void SetCurrentFuncReturnType(SymbolType type) {
current_func_ret_type_ = type;
}
// 符号表访问
SymbolTable& GetSymbolTable() { return sym_table_; } SymbolTable& GetSymbolTable() { return sym_table_; }
const SymbolTable& GetSymbolTable() const { return sym_table_; } const SymbolTable& GetSymbolTable() const { return sym_table_; }
// 作用域管理
void EnterScope() { sym_table_.EnterScope(); } void EnterScope() { sym_table_.EnterScope(); }
void LeaveScope() { sym_table_.LeaveScope(); } void LeaveScope() { sym_table_.LeaveScope(); }
size_t GetScopeDepth() const { return sym_table_.GetScopeDepth(); } size_t GetScopeDepth() const { return sym_table_.GetScopeDepth(); }
@ -71,6 +96,7 @@ class IRGenContext {
SymbolType current_func_ret_type_ = SymbolType::TYPE_UNKNOWN; SymbolType current_func_ret_type_ = SymbolType::TYPE_UNKNOWN;
}; };
// 与现有 IRGen/主流程保持兼容的语义上下文占位。
class SemanticContext { class SemanticContext {
public: public:
void BindVarUse(const SysYParser::LValueContext* use, void BindVarUse(const SysYParser::LValueContext* use,
@ -85,21 +111,45 @@ class SemanticContext {
} }
private: private:
std::unordered_map<const SysYParser::LValueContext*, SysYParser::VarDefContext*> std::unordered_map<const SysYParser::LValueContext*,
SysYParser::VarDefContext*>
var_uses_; var_uses_;
}; };
// 错误信息格式化工具函数
inline std::string FormatErrMsg(const std::string& msg, int line, int col) { inline std::string FormatErrMsg(const std::string& msg, int line, int col) {
std::ostringstream oss; std::ostringstream oss;
oss << "[行:" << line << ",列:" << col << "] " << msg; oss << "[行:" << line << ",列:" << col << "] " << msg;
return oss.str(); return oss.str();
} }
// 语义分析访问器 - 继承自生成的基类
class SemaVisitor : public SysYBaseVisitor { class SemaVisitor : public SysYBaseVisitor {
public: public:
explicit SemaVisitor(IRGenContext& ctx, SemanticContext* sema_ctx = nullptr) explicit SemaVisitor(IRGenContext& ctx) : ir_ctx_(ctx) {}
: ir_ctx_(ctx), sema_ctx_(sema_ctx) {}
// 必须实现的 ANTLR4 接口
std::any visit(antlr4::tree::ParseTree* tree) override {
if (tree) {
return tree->accept(this);
}
return std::any();
}
std::any visitTerminal(antlr4::tree::TerminalNode* node) override {
return std::any();
}
std::any visitErrorNode(antlr4::tree::ErrorNode* node) override {
if (node) {
int line = node->getSymbol()->getLine();
int col = node->getSymbol()->getCharPositionInLine() + 1;
ir_ctx_.RecordError(ErrorMsg("语法错误节点", line, col));
}
return std::any();
}
// 核心访问方法
std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override; std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override;
std::any visitDecl(SysYParser::DeclContext* ctx) override; std::any visitDecl(SysYParser::DeclContext* ctx) override;
std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override; std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override;
@ -133,19 +183,31 @@ class SemaVisitor : public SysYBaseVisitor {
std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override; std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override;
std::any visitConstExp(SysYParser::ConstExpContext* ctx) override; std::any visitConstExp(SysYParser::ConstExpContext* ctx) override;
// 通用子节点访问
std::any visitChildren(antlr4::tree::ParseTree* node) override {
std::any result;
if (node) {
for (auto* child : node->children) {
if (child) {
result = child->accept(this);
}
}
}
return result;
}
// 获取上下文引用
IRGenContext& GetContext() { return ir_ctx_; } IRGenContext& GetContext() { return ir_ctx_; }
const IRGenContext& GetContext() const { return ir_ctx_; } const IRGenContext& GetContext() const { return ir_ctx_; }
private: private:
void RecordNodeError(antlr4::ParserRuleContext* ctx, const std::string& msg);
IRGenContext& ir_ctx_; IRGenContext& ir_ctx_;
SemanticContext* sema_ctx_ = nullptr;
SymbolType current_decl_type_ = SymbolType::TYPE_UNKNOWN;
bool current_decl_is_const_ = false;
}; };
// 语义分析入口函数
void RunSemanticAnalysis(SysYParser::CompUnitContext* ctx, IRGenContext& ir_ctx); void RunSemanticAnalysis(SysYParser::CompUnitContext* ctx, IRGenContext& ir_ctx);
// 兼容旧流程入口。
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit); SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);
#endif // SEMANTIC_ANALYSIS_H #endif // SEMANTIC_ANALYSIS_H

@ -2,7 +2,7 @@ import os
import subprocess import subprocess
COMPILER = "./build/bin/compiler" COMPILER = "./build/bin/compiler"
TEST_DIR = "./test/test_case/functional" TEST_DIR = "./test/test_case/performance"
pass_cnt = 0 pass_cnt = 0
fail_cnt = 0 fail_cnt = 0

@ -60,7 +60,7 @@ if [[ "$run_exec" == true ]]; then
stdout_file="$out_dir/$stem.stdout" stdout_file="$out_dir/$stem.stdout"
actual_file="$out_dir/$stem.actual.out" actual_file="$out_dir/$stem.actual.out"
llc -filetype=obj "$out_file" -o "$obj" llc -filetype=obj "$out_file" -o "$obj"
clang -no-pie "$obj" sylib/sylib.c -o "$exe" -lm clang "$obj" -o "$exe"
echo "运行 $exe ..." echo "运行 $exe ..."
set +e set +e
if [[ -f "$stdin_file" ]]; then if [[ -f "$stdin_file" ]]; then
@ -81,7 +81,7 @@ if [[ "$run_exec" == true ]]; then
} > "$actual_file" } > "$actual_file"
if [[ -f "$expected_file" ]]; then if [[ -f "$expected_file" ]]; then
if diff -u <(sed -e 's/\r$//' -e '$a\\' "$expected_file") <(sed -e 's/\r$//' -e '$a\\' "$actual_file"); then if diff -u "$expected_file" "$actual_file"; then
echo "输出匹配: $expected_file" echo "输出匹配: $expected_file"
else else
echo "输出不匹配: $expected_file" >&2 echo "输出不匹配: $expected_file" >&2

@ -1,5 +1,5 @@
// Generated from SysY.g4 by ANTLR 4.7.2 // Generated from SysY.g4 by ANTLR 4.13.2
#include "SysYBaseVisitor.h" #include "SysYBaseVisitor.h"

@ -1,5 +1,5 @@
// Generated from SysY.g4 by ANTLR 4.7.2 // Generated from SysY.g4 by ANTLR 4.13.2
#pragma once #pragma once
@ -15,127 +15,131 @@
class SysYBaseVisitor : public SysYVisitor { class SysYBaseVisitor : public SysYVisitor {
public: public:
virtual antlrcpp::Any visitCompUnit(SysYParser::CompUnitContext *ctx) override { virtual std::any visitCompUnit(SysYParser::CompUnitContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitDecl(SysYParser::DeclContext *ctx) override { virtual std::any visitDecl(SysYParser::DeclContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitConstDecl(SysYParser::ConstDeclContext *ctx) override { virtual std::any visitConstDecl(SysYParser::ConstDeclContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitBType(SysYParser::BTypeContext *ctx) override { virtual std::any visitConstDef(SysYParser::ConstDefContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitConstDef(SysYParser::ConstDefContext *ctx) override { virtual std::any visitConstInitValue(SysYParser::ConstInitValueContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitConstInitVal(SysYParser::ConstInitValContext *ctx) override { virtual std::any visitVarDecl(SysYParser::VarDeclContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitVarDecl(SysYParser::VarDeclContext *ctx) override { virtual std::any visitBtype(SysYParser::BtypeContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitVarDef(SysYParser::VarDefContext *ctx) override { virtual std::any visitVarDef(SysYParser::VarDefContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitInitVal(SysYParser::InitValContext *ctx) override { virtual std::any visitInitValue(SysYParser::InitValueContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitFuncDef(SysYParser::FuncDefContext *ctx) override { virtual std::any visitFuncDef(SysYParser::FuncDefContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitFuncType(SysYParser::FuncTypeContext *ctx) override { virtual std::any visitFuncType(SysYParser::FuncTypeContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitFuncFParams(SysYParser::FuncFParamsContext *ctx) override { virtual std::any visitFuncFParams(SysYParser::FuncFParamsContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitFuncFParam(SysYParser::FuncFParamContext *ctx) override { virtual std::any visitFuncFParam(SysYParser::FuncFParamContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitBlock(SysYParser::BlockContext *ctx) override { virtual std::any visitBlockStmt(SysYParser::BlockStmtContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitBlockItem(SysYParser::BlockItemContext *ctx) override { virtual std::any visitBlockItem(SysYParser::BlockItemContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitStmt(SysYParser::StmtContext *ctx) override { virtual std::any visitStmt(SysYParser::StmtContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitExp(SysYParser::ExpContext *ctx) override { virtual std::any visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitCond(SysYParser::CondContext *ctx) override { virtual std::any visitExp(SysYParser::ExpContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitLVal(SysYParser::LValContext *ctx) override { virtual std::any visitCond(SysYParser::CondContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitPrimaryExp(SysYParser::PrimaryExpContext *ctx) override { virtual std::any visitLValue(SysYParser::LValueContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitNumber(SysYParser::NumberContext *ctx) override { virtual std::any visitPrimaryExp(SysYParser::PrimaryExpContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override { virtual std::any visitNumber(SysYParser::NumberContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitUnaryOp(SysYParser::UnaryOpContext *ctx) override { virtual std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override { virtual std::any visitUnaryOp(SysYParser::UnaryOpContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitMulExp(SysYParser::MulExpContext *ctx) override { virtual std::any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitAddExp(SysYParser::AddExpContext *ctx) override { virtual std::any visitMulExp(SysYParser::MulExpContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitRelExp(SysYParser::RelExpContext *ctx) override { virtual std::any visitAddExp(SysYParser::AddExpContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitEqExp(SysYParser::EqExpContext *ctx) override { virtual std::any visitRelExp(SysYParser::RelExpContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitLAndExp(SysYParser::LAndExpContext *ctx) override { virtual std::any visitEqExp(SysYParser::EqExpContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitLOrExp(SysYParser::LOrExpContext *ctx) override { virtual std::any visitLAndExp(SysYParser::LAndExpContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }
virtual antlrcpp::Any visitConstExp(SysYParser::ConstExpContext *ctx) override { virtual std::any visitLOrExp(SysYParser::LOrExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitConstExp(SysYParser::ConstExpContext *ctx) override {
return visitChildren(ctx); return visitChildren(ctx);
} }

@ -1,5 +1,5 @@
// Generated from SysY.g4 by ANTLR 4.7.2 // Generated from SysY.g4 by ANTLR 4.13.2
#include "SysYLexer.h" #include "SysYLexer.h"
@ -8,8 +8,223 @@
using namespace antlr4; using namespace antlr4;
using namespace antlr4;
namespace {
struct SysYLexerStaticData final {
SysYLexerStaticData(std::vector<std::string> ruleNames,
std::vector<std::string> channelNames,
std::vector<std::string> modeNames,
std::vector<std::string> literalNames,
std::vector<std::string> symbolicNames)
: ruleNames(std::move(ruleNames)), channelNames(std::move(channelNames)),
modeNames(std::move(modeNames)), literalNames(std::move(literalNames)),
symbolicNames(std::move(symbolicNames)),
vocabulary(this->literalNames, this->symbolicNames) {}
SysYLexerStaticData(const SysYLexerStaticData&) = delete;
SysYLexerStaticData(SysYLexerStaticData&&) = delete;
SysYLexerStaticData& operator=(const SysYLexerStaticData&) = delete;
SysYLexerStaticData& operator=(SysYLexerStaticData&&) = delete;
std::vector<antlr4::dfa::DFA> decisionToDFA;
antlr4::atn::PredictionContextCache sharedContextCache;
const std::vector<std::string> ruleNames;
const std::vector<std::string> channelNames;
const std::vector<std::string> modeNames;
const std::vector<std::string> literalNames;
const std::vector<std::string> symbolicNames;
const antlr4::dfa::Vocabulary vocabulary;
antlr4::atn::SerializedATNView serializedATN;
std::unique_ptr<antlr4::atn::ATN> atn;
};
::antlr4::internal::OnceFlag sysylexerLexerOnceFlag;
#if ANTLR4_USE_THREAD_LOCAL_CACHE
static thread_local
#endif
std::unique_ptr<SysYLexerStaticData> sysylexerLexerStaticData = nullptr;
void sysylexerLexerInitialize() {
#if ANTLR4_USE_THREAD_LOCAL_CACHE
if (sysylexerLexerStaticData != nullptr) {
return;
}
#else
assert(sysylexerLexerStaticData == nullptr);
#endif
auto staticData = std::make_unique<SysYLexerStaticData>(
std::vector<std::string>{
"CONST", "INT", "FLOAT", "VOID", "IF", "ELSE", "WHILE", "BREAK", "CONTINUE",
"RETURN", "ASSIGN", "EQ", "NE", "LT", "GT", "LE", "GE", "ADD", "SUB",
"MUL", "DIV", "MOD", "NOT", "AND", "OR", "LPAREN", "RPAREN", "LBRACK",
"RBRACK", "LBRACE", "RBRACE", "COMMA", "SEMICOLON", "ID", "FLITERAL",
"ILITERAL", "DEC_INT", "OCT_INT", "HEX_INT", "DECIMAL_FLOAT", "HEX_FLOAT",
"EXP", "WS", "LINECOMMENT", "BLOCKCOMMENT"
},
std::vector<std::string>{
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
},
std::vector<std::string>{
"DEFAULT_MODE"
},
std::vector<std::string>{
"", "'const'", "'int'", "'float'", "'void'", "'if'", "'else'", "'while'",
"'break'", "'continue'", "'return'", "'='", "'=='", "'!='", "'<'",
"'>'", "'<='", "'>='", "'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "'&&'",
"'||'", "'('", "')'", "'['", "']'", "'{'", "'}'", "','", "';'"
},
std::vector<std::string>{
"", "CONST", "INT", "FLOAT", "VOID", "IF", "ELSE", "WHILE", "BREAK",
"CONTINUE", "RETURN", "ASSIGN", "EQ", "NE", "LT", "GT", "LE", "GE",
"ADD", "SUB", "MUL", "DIV", "MOD", "NOT", "AND", "OR", "LPAREN", "RPAREN",
"LBRACK", "RBRACK", "LBRACE", "RBRACE", "COMMA", "SEMICOLON", "ID",
"FLITERAL", "ILITERAL", "WS", "LINECOMMENT", "BLOCKCOMMENT"
}
);
static const int32_t serializedATNSegment[] = {
4,0,39,353,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,
6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,
7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,
7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,
7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,
7,35,2,36,7,36,2,37,7,37,2,38,7,38,2,39,7,39,2,40,7,40,2,41,7,41,2,42,
7,42,2,43,7,43,2,44,7,44,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,2,
1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,3,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,
5,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,
1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,11,1,11,1,11,
1,12,1,12,1,12,1,13,1,13,1,14,1,14,1,15,1,15,1,15,1,16,1,16,1,16,1,17,
1,17,1,18,1,18,1,19,1,19,1,20,1,20,1,21,1,21,1,22,1,22,1,23,1,23,1,23,
1,24,1,24,1,24,1,25,1,25,1,26,1,26,1,27,1,27,1,28,1,28,1,29,1,29,1,30,
1,30,1,31,1,31,1,32,1,32,1,33,1,33,5,33,203,8,33,10,33,12,33,206,9,33,
1,34,1,34,3,34,210,8,34,1,35,1,35,1,35,3,35,215,8,35,1,36,1,36,1,36,5,
36,220,8,36,10,36,12,36,223,9,36,3,36,225,8,36,1,37,1,37,4,37,229,8,37,
11,37,12,37,230,1,38,1,38,1,38,4,38,236,8,38,11,38,12,38,237,1,39,4,39,
241,8,39,11,39,12,39,242,1,39,1,39,5,39,247,8,39,10,39,12,39,250,9,39,
1,39,3,39,253,8,39,1,39,1,39,4,39,257,8,39,11,39,12,39,258,1,39,3,39,
262,8,39,1,39,4,39,265,8,39,11,39,12,39,266,1,39,3,39,270,8,39,1,40,1,
40,1,40,4,40,275,8,40,11,40,12,40,276,1,40,1,40,5,40,281,8,40,10,40,12,
40,284,9,40,3,40,286,8,40,1,40,1,40,3,40,290,8,40,1,40,4,40,293,8,40,
11,40,12,40,294,1,40,1,40,1,40,1,40,4,40,301,8,40,11,40,12,40,302,1,40,
1,40,3,40,307,8,40,1,40,4,40,310,8,40,11,40,12,40,311,3,40,314,8,40,1,
41,1,41,3,41,318,8,41,1,41,4,41,321,8,41,11,41,12,41,322,1,42,1,42,1,
42,1,42,1,43,1,43,1,43,1,43,5,43,333,8,43,10,43,12,43,336,9,43,1,43,1,
43,1,44,1,44,1,44,1,44,5,44,344,8,44,10,44,12,44,347,9,44,1,44,1,44,1,
44,1,44,1,44,1,345,0,45,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,
21,11,23,12,25,13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,
22,45,23,47,24,49,25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,
67,34,69,35,71,36,73,0,75,0,77,0,79,0,81,0,83,0,85,37,87,38,89,39,1,0,
12,3,0,65,90,95,95,97,122,4,0,48,57,65,90,95,95,97,122,1,0,49,57,1,0,
48,57,1,0,48,55,2,0,88,88,120,120,3,0,48,57,65,70,97,102,2,0,80,80,112,
112,2,0,43,43,45,45,2,0,69,69,101,101,3,0,9,10,13,13,32,32,2,0,10,10,
13,13,375,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,
0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,
1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,
0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,
0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,
1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,
0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,85,1,0,0,0,
0,87,1,0,0,0,0,89,1,0,0,0,1,91,1,0,0,0,3,97,1,0,0,0,5,101,1,0,0,0,7,107,
1,0,0,0,9,112,1,0,0,0,11,115,1,0,0,0,13,120,1,0,0,0,15,126,1,0,0,0,17,
132,1,0,0,0,19,141,1,0,0,0,21,148,1,0,0,0,23,150,1,0,0,0,25,153,1,0,0,
0,27,156,1,0,0,0,29,158,1,0,0,0,31,160,1,0,0,0,33,163,1,0,0,0,35,166,
1,0,0,0,37,168,1,0,0,0,39,170,1,0,0,0,41,172,1,0,0,0,43,174,1,0,0,0,45,
176,1,0,0,0,47,178,1,0,0,0,49,181,1,0,0,0,51,184,1,0,0,0,53,186,1,0,0,
0,55,188,1,0,0,0,57,190,1,0,0,0,59,192,1,0,0,0,61,194,1,0,0,0,63,196,
1,0,0,0,65,198,1,0,0,0,67,200,1,0,0,0,69,209,1,0,0,0,71,214,1,0,0,0,73,
224,1,0,0,0,75,226,1,0,0,0,77,232,1,0,0,0,79,269,1,0,0,0,81,313,1,0,0,
0,83,315,1,0,0,0,85,324,1,0,0,0,87,328,1,0,0,0,89,339,1,0,0,0,91,92,5,
99,0,0,92,93,5,111,0,0,93,94,5,110,0,0,94,95,5,115,0,0,95,96,5,116,0,
0,96,2,1,0,0,0,97,98,5,105,0,0,98,99,5,110,0,0,99,100,5,116,0,0,100,4,
1,0,0,0,101,102,5,102,0,0,102,103,5,108,0,0,103,104,5,111,0,0,104,105,
5,97,0,0,105,106,5,116,0,0,106,6,1,0,0,0,107,108,5,118,0,0,108,109,5,
111,0,0,109,110,5,105,0,0,110,111,5,100,0,0,111,8,1,0,0,0,112,113,5,105,
0,0,113,114,5,102,0,0,114,10,1,0,0,0,115,116,5,101,0,0,116,117,5,108,
0,0,117,118,5,115,0,0,118,119,5,101,0,0,119,12,1,0,0,0,120,121,5,119,
0,0,121,122,5,104,0,0,122,123,5,105,0,0,123,124,5,108,0,0,124,125,5,101,
0,0,125,14,1,0,0,0,126,127,5,98,0,0,127,128,5,114,0,0,128,129,5,101,0,
0,129,130,5,97,0,0,130,131,5,107,0,0,131,16,1,0,0,0,132,133,5,99,0,0,
133,134,5,111,0,0,134,135,5,110,0,0,135,136,5,116,0,0,136,137,5,105,0,
0,137,138,5,110,0,0,138,139,5,117,0,0,139,140,5,101,0,0,140,18,1,0,0,
0,141,142,5,114,0,0,142,143,5,101,0,0,143,144,5,116,0,0,144,145,5,117,
0,0,145,146,5,114,0,0,146,147,5,110,0,0,147,20,1,0,0,0,148,149,5,61,0,
0,149,22,1,0,0,0,150,151,5,61,0,0,151,152,5,61,0,0,152,24,1,0,0,0,153,
154,5,33,0,0,154,155,5,61,0,0,155,26,1,0,0,0,156,157,5,60,0,0,157,28,
1,0,0,0,158,159,5,62,0,0,159,30,1,0,0,0,160,161,5,60,0,0,161,162,5,61,
0,0,162,32,1,0,0,0,163,164,5,62,0,0,164,165,5,61,0,0,165,34,1,0,0,0,166,
167,5,43,0,0,167,36,1,0,0,0,168,169,5,45,0,0,169,38,1,0,0,0,170,171,5,
42,0,0,171,40,1,0,0,0,172,173,5,47,0,0,173,42,1,0,0,0,174,175,5,37,0,
0,175,44,1,0,0,0,176,177,5,33,0,0,177,46,1,0,0,0,178,179,5,38,0,0,179,
180,5,38,0,0,180,48,1,0,0,0,181,182,5,124,0,0,182,183,5,124,0,0,183,50,
1,0,0,0,184,185,5,40,0,0,185,52,1,0,0,0,186,187,5,41,0,0,187,54,1,0,0,
0,188,189,5,91,0,0,189,56,1,0,0,0,190,191,5,93,0,0,191,58,1,0,0,0,192,
193,5,123,0,0,193,60,1,0,0,0,194,195,5,125,0,0,195,62,1,0,0,0,196,197,
5,44,0,0,197,64,1,0,0,0,198,199,5,59,0,0,199,66,1,0,0,0,200,204,7,0,0,
0,201,203,7,1,0,0,202,201,1,0,0,0,203,206,1,0,0,0,204,202,1,0,0,0,204,
205,1,0,0,0,205,68,1,0,0,0,206,204,1,0,0,0,207,210,3,79,39,0,208,210,
3,81,40,0,209,207,1,0,0,0,209,208,1,0,0,0,210,70,1,0,0,0,211,215,3,77,
38,0,212,215,3,75,37,0,213,215,3,73,36,0,214,211,1,0,0,0,214,212,1,0,
0,0,214,213,1,0,0,0,215,72,1,0,0,0,216,225,5,48,0,0,217,221,7,2,0,0,218,
220,7,3,0,0,219,218,1,0,0,0,220,223,1,0,0,0,221,219,1,0,0,0,221,222,1,
0,0,0,222,225,1,0,0,0,223,221,1,0,0,0,224,216,1,0,0,0,224,217,1,0,0,0,
225,74,1,0,0,0,226,228,5,48,0,0,227,229,7,4,0,0,228,227,1,0,0,0,229,230,
1,0,0,0,230,228,1,0,0,0,230,231,1,0,0,0,231,76,1,0,0,0,232,233,5,48,0,
0,233,235,7,5,0,0,234,236,7,6,0,0,235,234,1,0,0,0,236,237,1,0,0,0,237,
235,1,0,0,0,237,238,1,0,0,0,238,78,1,0,0,0,239,241,7,3,0,0,240,239,1,
0,0,0,241,242,1,0,0,0,242,240,1,0,0,0,242,243,1,0,0,0,243,244,1,0,0,0,
244,248,5,46,0,0,245,247,7,3,0,0,246,245,1,0,0,0,247,250,1,0,0,0,248,
246,1,0,0,0,248,249,1,0,0,0,249,252,1,0,0,0,250,248,1,0,0,0,251,253,3,
83,41,0,252,251,1,0,0,0,252,253,1,0,0,0,253,270,1,0,0,0,254,256,5,46,
0,0,255,257,7,3,0,0,256,255,1,0,0,0,257,258,1,0,0,0,258,256,1,0,0,0,258,
259,1,0,0,0,259,261,1,0,0,0,260,262,3,83,41,0,261,260,1,0,0,0,261,262,
1,0,0,0,262,270,1,0,0,0,263,265,7,3,0,0,264,263,1,0,0,0,265,266,1,0,0,
0,266,264,1,0,0,0,266,267,1,0,0,0,267,268,1,0,0,0,268,270,3,83,41,0,269,
240,1,0,0,0,269,254,1,0,0,0,269,264,1,0,0,0,270,80,1,0,0,0,271,272,5,
48,0,0,272,274,7,5,0,0,273,275,7,6,0,0,274,273,1,0,0,0,275,276,1,0,0,
0,276,274,1,0,0,0,276,277,1,0,0,0,277,285,1,0,0,0,278,282,5,46,0,0,279,
281,7,6,0,0,280,279,1,0,0,0,281,284,1,0,0,0,282,280,1,0,0,0,282,283,1,
0,0,0,283,286,1,0,0,0,284,282,1,0,0,0,285,278,1,0,0,0,285,286,1,0,0,0,
286,287,1,0,0,0,287,289,7,7,0,0,288,290,7,8,0,0,289,288,1,0,0,0,289,290,
1,0,0,0,290,292,1,0,0,0,291,293,7,3,0,0,292,291,1,0,0,0,293,294,1,0,0,
0,294,292,1,0,0,0,294,295,1,0,0,0,295,314,1,0,0,0,296,297,5,48,0,0,297,
298,7,5,0,0,298,300,5,46,0,0,299,301,7,6,0,0,300,299,1,0,0,0,301,302,
1,0,0,0,302,300,1,0,0,0,302,303,1,0,0,0,303,304,1,0,0,0,304,306,7,7,0,
0,305,307,7,8,0,0,306,305,1,0,0,0,306,307,1,0,0,0,307,309,1,0,0,0,308,
310,7,3,0,0,309,308,1,0,0,0,310,311,1,0,0,0,311,309,1,0,0,0,311,312,1,
0,0,0,312,314,1,0,0,0,313,271,1,0,0,0,313,296,1,0,0,0,314,82,1,0,0,0,
315,317,7,9,0,0,316,318,7,8,0,0,317,316,1,0,0,0,317,318,1,0,0,0,318,320,
1,0,0,0,319,321,7,3,0,0,320,319,1,0,0,0,321,322,1,0,0,0,322,320,1,0,0,
0,322,323,1,0,0,0,323,84,1,0,0,0,324,325,7,10,0,0,325,326,1,0,0,0,326,
327,6,42,0,0,327,86,1,0,0,0,328,329,5,47,0,0,329,330,5,47,0,0,330,334,
1,0,0,0,331,333,8,11,0,0,332,331,1,0,0,0,333,336,1,0,0,0,334,332,1,0,
0,0,334,335,1,0,0,0,335,337,1,0,0,0,336,334,1,0,0,0,337,338,6,43,0,0,
338,88,1,0,0,0,339,340,5,47,0,0,340,341,5,42,0,0,341,345,1,0,0,0,342,
344,9,0,0,0,343,342,1,0,0,0,344,347,1,0,0,0,345,346,1,0,0,0,345,343,1,
0,0,0,346,348,1,0,0,0,347,345,1,0,0,0,348,349,5,42,0,0,349,350,5,47,0,
0,350,351,1,0,0,0,351,352,6,44,0,0,352,90,1,0,0,0,28,0,204,209,214,221,
224,230,237,242,248,252,258,261,266,269,276,282,285,289,294,302,306,311,
313,317,322,334,345,1,6,0,0
};
staticData->serializedATN = antlr4::atn::SerializedATNView(serializedATNSegment, sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0]));
antlr4::atn::ATNDeserializer deserializer;
staticData->atn = deserializer.deserialize(staticData->serializedATN);
const size_t count = staticData->atn->getNumberOfDecisions();
staticData->decisionToDFA.reserve(count);
for (size_t i = 0; i < count; i++) {
staticData->decisionToDFA.emplace_back(staticData->atn->getDecisionState(i), i);
}
sysylexerLexerStaticData = std::move(staticData);
}
}
SysYLexer::SysYLexer(CharStream *input) : Lexer(input) { SysYLexer::SysYLexer(CharStream *input) : Lexer(input) {
_interpreter = new atn::LexerATNSimulator(this, _atn, _decisionToDFA, _sharedContextCache); SysYLexer::initialize();
_interpreter = new atn::LexerATNSimulator(this, *sysylexerLexerStaticData->atn, sysylexerLexerStaticData->decisionToDFA, sysylexerLexerStaticData->sharedContextCache);
} }
SysYLexer::~SysYLexer() { SysYLexer::~SysYLexer() {
@ -21,357 +236,36 @@ std::string SysYLexer::getGrammarFileName() const {
} }
const std::vector<std::string>& SysYLexer::getRuleNames() const { const std::vector<std::string>& SysYLexer::getRuleNames() const {
return _ruleNames; return sysylexerLexerStaticData->ruleNames;
} }
const std::vector<std::string>& SysYLexer::getChannelNames() const { const std::vector<std::string>& SysYLexer::getChannelNames() const {
return _channelNames; return sysylexerLexerStaticData->channelNames;
} }
const std::vector<std::string>& SysYLexer::getModeNames() const { const std::vector<std::string>& SysYLexer::getModeNames() const {
return _modeNames; return sysylexerLexerStaticData->modeNames;
} }
const std::vector<std::string>& SysYLexer::getTokenNames() const { const dfa::Vocabulary& SysYLexer::getVocabulary() const {
return _tokenNames; return sysylexerLexerStaticData->vocabulary;
} }
dfa::Vocabulary& SysYLexer::getVocabulary() const { antlr4::atn::SerializedATNView SysYLexer::getSerializedATN() const {
return _vocabulary; return sysylexerLexerStaticData->serializedATN;
}
const std::vector<uint16_t> SysYLexer::getSerializedATN() const {
return _serializedATN;
} }
const atn::ATN& SysYLexer::getATN() const { const atn::ATN& SysYLexer::getATN() const {
return _atn; return *sysylexerLexerStaticData->atn;
}
// Static vars and initialization.
std::vector<dfa::DFA> SysYLexer::_decisionToDFA;
atn::PredictionContextCache SysYLexer::_sharedContextCache;
// We own the ATN which in turn owns the ATN states.
atn::ATN SysYLexer::_atn;
std::vector<uint16_t> SysYLexer::_serializedATN;
std::vector<std::string> SysYLexer::_ruleNames = {
u8"T__0", u8"T__1", u8"T__2", u8"T__3", u8"T__4", u8"T__5", u8"T__6",
u8"T__7", u8"T__8", u8"T__9", u8"T__10", u8"T__11", u8"T__12", u8"T__13",
u8"T__14", u8"T__15", u8"T__16", u8"T__17", u8"T__18", u8"T__19", u8"T__20",
u8"T__21", u8"T__22", u8"T__23", u8"T__24", u8"T__25", u8"T__26", u8"T__27",
u8"T__28", u8"T__29", u8"T__30", u8"T__31", u8"T__32", u8"DIGIT", u8"HEXDIGIT",
u8"EXP", u8"PEXP", u8"FloatConst", u8"IntConst", u8"Ident", u8"WS", u8"LINE_COMMENT",
u8"BLOCK_COMMENT"
};
std::vector<std::string> SysYLexer::_channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
std::vector<std::string> SysYLexer::_modeNames = {
u8"DEFAULT_MODE"
};
std::vector<std::string> SysYLexer::_literalNames = {
"", u8"'const'", u8"','", u8"';'", u8"'int'", u8"'float'", u8"'['", u8"']'",
u8"'='", u8"'{'", u8"'}'", u8"'('", u8"')'", u8"'void'", u8"'if'", u8"'else'",
u8"'while'", u8"'break'", u8"'continue'", u8"'return'", u8"'+'", u8"'-'",
u8"'!'", u8"'*'", u8"'/'", u8"'%'", u8"'<'", u8"'>'", u8"'<='", u8"'>='",
u8"'=='", u8"'!='", u8"'&&'", u8"'||'"
};
std::vector<std::string> SysYLexer::_symbolicNames = {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", u8"FloatConst",
u8"IntConst", u8"Ident", u8"WS", u8"LINE_COMMENT", u8"BLOCK_COMMENT"
};
dfa::Vocabulary SysYLexer::_vocabulary(_literalNames, _symbolicNames);
std::vector<std::string> SysYLexer::_tokenNames;
SysYLexer::Initializer::Initializer() {
// This code could be in a static initializer lambda, but VS doesn't allow access to private class members from there.
for (size_t i = 0; i < _symbolicNames.size(); ++i) {
std::string name = _vocabulary.getLiteralName(i);
if (name.empty()) {
name = _vocabulary.getSymbolicName(i);
} }
if (name.empty()) {
_tokenNames.push_back("<INVALID>");
} else {
_tokenNames.push_back(name);
}
}
_serializedATN = {
0x3, 0x608b, 0xa72a, 0x8133, 0xb9ed, 0x417c, 0x3be7, 0x7786, 0x5964,
0x2, 0x29, 0x160, 0x8, 0x1, 0x4, 0x2, 0x9, 0x2, 0x4, 0x3, 0x9, 0x3,
0x4, 0x4, 0x9, 0x4, 0x4, 0x5, 0x9, 0x5, 0x4, 0x6, 0x9, 0x6, 0x4, 0x7,
0x9, 0x7, 0x4, 0x8, 0x9, 0x8, 0x4, 0x9, 0x9, 0x9, 0x4, 0xa, 0x9, 0xa,
0x4, 0xb, 0x9, 0xb, 0x4, 0xc, 0x9, 0xc, 0x4, 0xd, 0x9, 0xd, 0x4, 0xe,
0x9, 0xe, 0x4, 0xf, 0x9, 0xf, 0x4, 0x10, 0x9, 0x10, 0x4, 0x11, 0x9,
0x11, 0x4, 0x12, 0x9, 0x12, 0x4, 0x13, 0x9, 0x13, 0x4, 0x14, 0x9, 0x14,
0x4, 0x15, 0x9, 0x15, 0x4, 0x16, 0x9, 0x16, 0x4, 0x17, 0x9, 0x17, 0x4,
0x18, 0x9, 0x18, 0x4, 0x19, 0x9, 0x19, 0x4, 0x1a, 0x9, 0x1a, 0x4, 0x1b,
0x9, 0x1b, 0x4, 0x1c, 0x9, 0x1c, 0x4, 0x1d, 0x9, 0x1d, 0x4, 0x1e, 0x9,
0x1e, 0x4, 0x1f, 0x9, 0x1f, 0x4, 0x20, 0x9, 0x20, 0x4, 0x21, 0x9, 0x21,
0x4, 0x22, 0x9, 0x22, 0x4, 0x23, 0x9, 0x23, 0x4, 0x24, 0x9, 0x24, 0x4,
0x25, 0x9, 0x25, 0x4, 0x26, 0x9, 0x26, 0x4, 0x27, 0x9, 0x27, 0x4, 0x28,
0x9, 0x28, 0x4, 0x29, 0x9, 0x29, 0x4, 0x2a, 0x9, 0x2a, 0x4, 0x2b, 0x9,
0x2b, 0x4, 0x2c, 0x9, 0x2c, 0x3, 0x2, 0x3, 0x2, 0x3, 0x2, 0x3, 0x2,
0x3, 0x2, 0x3, 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x4, 0x3, 0x5,
0x3, 0x5, 0x3, 0x5, 0x3, 0x5, 0x3, 0x6, 0x3, 0x6, 0x3, 0x6, 0x3, 0x6,
0x3, 0x6, 0x3, 0x6, 0x3, 0x7, 0x3, 0x7, 0x3, 0x8, 0x3, 0x8, 0x3, 0x9,
0x3, 0x9, 0x3, 0xa, 0x3, 0xa, 0x3, 0xb, 0x3, 0xb, 0x3, 0xc, 0x3, 0xc,
0x3, 0xd, 0x3, 0xd, 0x3, 0xe, 0x3, 0xe, 0x3, 0xe, 0x3, 0xe, 0x3, 0xe,
0x3, 0xf, 0x3, 0xf, 0x3, 0xf, 0x3, 0x10, 0x3, 0x10, 0x3, 0x10, 0x3,
0x10, 0x3, 0x10, 0x3, 0x11, 0x3, 0x11, 0x3, 0x11, 0x3, 0x11, 0x3, 0x11,
0x3, 0x11, 0x3, 0x12, 0x3, 0x12, 0x3, 0x12, 0x3, 0x12, 0x3, 0x12, 0x3,
0x12, 0x3, 0x13, 0x3, 0x13, 0x3, 0x13, 0x3, 0x13, 0x3, 0x13, 0x3, 0x13,
0x3, 0x13, 0x3, 0x13, 0x3, 0x13, 0x3, 0x14, 0x3, 0x14, 0x3, 0x14, 0x3,
0x14, 0x3, 0x14, 0x3, 0x14, 0x3, 0x14, 0x3, 0x15, 0x3, 0x15, 0x3, 0x16,
0x3, 0x16, 0x3, 0x17, 0x3, 0x17, 0x3, 0x18, 0x3, 0x18, 0x3, 0x19, 0x3,
0x19, 0x3, 0x1a, 0x3, 0x1a, 0x3, 0x1b, 0x3, 0x1b, 0x3, 0x1c, 0x3, 0x1c,
0x3, 0x1d, 0x3, 0x1d, 0x3, 0x1d, 0x3, 0x1e, 0x3, 0x1e, 0x3, 0x1e, 0x3,
0x1f, 0x3, 0x1f, 0x3, 0x1f, 0x3, 0x20, 0x3, 0x20, 0x3, 0x20, 0x3, 0x21,
0x3, 0x21, 0x3, 0x21, 0x3, 0x22, 0x3, 0x22, 0x3, 0x22, 0x3, 0x23, 0x3,
0x23, 0x3, 0x24, 0x3, 0x24, 0x3, 0x25, 0x3, 0x25, 0x5, 0x25, 0xcd, 0xa,
0x25, 0x3, 0x25, 0x6, 0x25, 0xd0, 0xa, 0x25, 0xd, 0x25, 0xe, 0x25, 0xd1,
0x3, 0x26, 0x3, 0x26, 0x5, 0x26, 0xd6, 0xa, 0x26, 0x3, 0x26, 0x6, 0x26,
0xd9, 0xa, 0x26, 0xd, 0x26, 0xe, 0x26, 0xda, 0x3, 0x27, 0x3, 0x27, 0x3,
0x27, 0x3, 0x27, 0x5, 0x27, 0xe1, 0xa, 0x27, 0x3, 0x27, 0x6, 0x27, 0xe4,
0xa, 0x27, 0xd, 0x27, 0xe, 0x27, 0xe5, 0x3, 0x27, 0x3, 0x27, 0x7, 0x27,
0xea, 0xa, 0x27, 0xc, 0x27, 0xe, 0x27, 0xed, 0xb, 0x27, 0x3, 0x27, 0x3,
0x27, 0x6, 0x27, 0xf1, 0xa, 0x27, 0xd, 0x27, 0xe, 0x27, 0xf2, 0x3, 0x27,
0x6, 0x27, 0xf6, 0xa, 0x27, 0xd, 0x27, 0xe, 0x27, 0xf7, 0x5, 0x27, 0xfa,
0xa, 0x27, 0x3, 0x27, 0x3, 0x27, 0x3, 0x27, 0x3, 0x27, 0x6, 0x27, 0x100,
0xa, 0x27, 0xd, 0x27, 0xe, 0x27, 0x101, 0x3, 0x27, 0x5, 0x27, 0x105,
0xa, 0x27, 0x3, 0x27, 0x6, 0x27, 0x108, 0xa, 0x27, 0xd, 0x27, 0xe, 0x27,
0x109, 0x3, 0x27, 0x3, 0x27, 0x7, 0x27, 0x10e, 0xa, 0x27, 0xc, 0x27,
0xe, 0x27, 0x111, 0xb, 0x27, 0x3, 0x27, 0x5, 0x27, 0x114, 0xa, 0x27,
0x3, 0x27, 0x6, 0x27, 0x117, 0xa, 0x27, 0xd, 0x27, 0xe, 0x27, 0x118,
0x3, 0x27, 0x3, 0x27, 0x5, 0x27, 0x11d, 0xa, 0x27, 0x3, 0x28, 0x3, 0x28,
0x3, 0x28, 0x7, 0x28, 0x122, 0xa, 0x28, 0xc, 0x28, 0xe, 0x28, 0x125,
0xb, 0x28, 0x3, 0x28, 0x3, 0x28, 0x6, 0x28, 0x129, 0xa, 0x28, 0xd, 0x28,
0xe, 0x28, 0x12a, 0x3, 0x28, 0x3, 0x28, 0x3, 0x28, 0x3, 0x28, 0x5, 0x28,
0x131, 0xa, 0x28, 0x3, 0x28, 0x6, 0x28, 0x134, 0xa, 0x28, 0xd, 0x28,
0xe, 0x28, 0x135, 0x5, 0x28, 0x138, 0xa, 0x28, 0x3, 0x29, 0x3, 0x29,
0x7, 0x29, 0x13c, 0xa, 0x29, 0xc, 0x29, 0xe, 0x29, 0x13f, 0xb, 0x29,
0x3, 0x2a, 0x6, 0x2a, 0x142, 0xa, 0x2a, 0xd, 0x2a, 0xe, 0x2a, 0x143,
0x3, 0x2a, 0x3, 0x2a, 0x3, 0x2b, 0x3, 0x2b, 0x3, 0x2b, 0x3, 0x2b, 0x7,
0x2b, 0x14c, 0xa, 0x2b, 0xc, 0x2b, 0xe, 0x2b, 0x14f, 0xb, 0x2b, 0x3,
0x2b, 0x3, 0x2b, 0x3, 0x2c, 0x3, 0x2c, 0x3, 0x2c, 0x3, 0x2c, 0x7, 0x2c,
0x157, 0xa, 0x2c, 0xc, 0x2c, 0xe, 0x2c, 0x15a, 0xb, 0x2c, 0x3, 0x2c,
0x3, 0x2c, 0x3, 0x2c, 0x3, 0x2c, 0x3, 0x2c, 0x3, 0x158, 0x2, 0x2d, 0x3,
0x3, 0x5, 0x4, 0x7, 0x5, 0x9, 0x6, 0xb, 0x7, 0xd, 0x8, 0xf, 0x9, 0x11,
0xa, 0x13, 0xb, 0x15, 0xc, 0x17, 0xd, 0x19, 0xe, 0x1b, 0xf, 0x1d, 0x10,
0x1f, 0x11, 0x21, 0x12, 0x23, 0x13, 0x25, 0x14, 0x27, 0x15, 0x29, 0x16,
0x2b, 0x17, 0x2d, 0x18, 0x2f, 0x19, 0x31, 0x1a, 0x33, 0x1b, 0x35, 0x1c,
0x37, 0x1d, 0x39, 0x1e, 0x3b, 0x1f, 0x3d, 0x20, 0x3f, 0x21, 0x41, 0x22,
0x43, 0x23, 0x45, 0x2, 0x47, 0x2, 0x49, 0x2, 0x4b, 0x2, 0x4d, 0x24,
0x4f, 0x25, 0x51, 0x26, 0x53, 0x27, 0x55, 0x28, 0x57, 0x29, 0x3, 0x2,
0xd, 0x3, 0x2, 0x32, 0x3b, 0x5, 0x2, 0x32, 0x3b, 0x43, 0x48, 0x63, 0x68,
0x4, 0x2, 0x47, 0x47, 0x67, 0x67, 0x4, 0x2, 0x2d, 0x2d, 0x2f, 0x2f,
0x4, 0x2, 0x52, 0x52, 0x72, 0x72, 0x3, 0x2, 0x33, 0x3b, 0x3, 0x2, 0x32,
0x39, 0x5, 0x2, 0x43, 0x5c, 0x61, 0x61, 0x63, 0x7c, 0x6, 0x2, 0x32,
0x3b, 0x43, 0x5c, 0x61, 0x61, 0x63, 0x7c, 0x5, 0x2, 0xb, 0xc, 0xf, 0xf,
0x22, 0x22, 0x4, 0x2, 0xc, 0xc, 0xf, 0xf, 0x2, 0x17a, 0x2, 0x3, 0x3,
0x2, 0x2, 0x2, 0x2, 0x5, 0x3, 0x2, 0x2, 0x2, 0x2, 0x7, 0x3, 0x2, 0x2,
0x2, 0x2, 0x9, 0x3, 0x2, 0x2, 0x2, 0x2, 0xb, 0x3, 0x2, 0x2, 0x2, 0x2,
0xd, 0x3, 0x2, 0x2, 0x2, 0x2, 0xf, 0x3, 0x2, 0x2, 0x2, 0x2, 0x11, 0x3,
0x2, 0x2, 0x2, 0x2, 0x13, 0x3, 0x2, 0x2, 0x2, 0x2, 0x15, 0x3, 0x2, 0x2,
0x2, 0x2, 0x17, 0x3, 0x2, 0x2, 0x2, 0x2, 0x19, 0x3, 0x2, 0x2, 0x2, 0x2,
0x1b, 0x3, 0x2, 0x2, 0x2, 0x2, 0x1d, 0x3, 0x2, 0x2, 0x2, 0x2, 0x1f,
0x3, 0x2, 0x2, 0x2, 0x2, 0x21, 0x3, 0x2, 0x2, 0x2, 0x2, 0x23, 0x3, 0x2,
0x2, 0x2, 0x2, 0x25, 0x3, 0x2, 0x2, 0x2, 0x2, 0x27, 0x3, 0x2, 0x2, 0x2,
0x2, 0x29, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2b, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2d,
0x3, 0x2, 0x2, 0x2, 0x2, 0x2f, 0x3, 0x2, 0x2, 0x2, 0x2, 0x31, 0x3, 0x2,
0x2, 0x2, 0x2, 0x33, 0x3, 0x2, 0x2, 0x2, 0x2, 0x35, 0x3, 0x2, 0x2, 0x2,
0x2, 0x37, 0x3, 0x2, 0x2, 0x2, 0x2, 0x39, 0x3, 0x2, 0x2, 0x2, 0x2, 0x3b,
0x3, 0x2, 0x2, 0x2, 0x2, 0x3d, 0x3, 0x2, 0x2, 0x2, 0x2, 0x3f, 0x3, 0x2,
0x2, 0x2, 0x2, 0x41, 0x3, 0x2, 0x2, 0x2, 0x2, 0x43, 0x3, 0x2, 0x2, 0x2,
0x2, 0x4d, 0x3, 0x2, 0x2, 0x2, 0x2, 0x4f, 0x3, 0x2, 0x2, 0x2, 0x2, 0x51,
0x3, 0x2, 0x2, 0x2, 0x2, 0x53, 0x3, 0x2, 0x2, 0x2, 0x2, 0x55, 0x3, 0x2,
0x2, 0x2, 0x2, 0x57, 0x3, 0x2, 0x2, 0x2, 0x3, 0x59, 0x3, 0x2, 0x2, 0x2,
0x5, 0x5f, 0x3, 0x2, 0x2, 0x2, 0x7, 0x61, 0x3, 0x2, 0x2, 0x2, 0x9, 0x63,
0x3, 0x2, 0x2, 0x2, 0xb, 0x67, 0x3, 0x2, 0x2, 0x2, 0xd, 0x6d, 0x3, 0x2,
0x2, 0x2, 0xf, 0x6f, 0x3, 0x2, 0x2, 0x2, 0x11, 0x71, 0x3, 0x2, 0x2,
0x2, 0x13, 0x73, 0x3, 0x2, 0x2, 0x2, 0x15, 0x75, 0x3, 0x2, 0x2, 0x2,
0x17, 0x77, 0x3, 0x2, 0x2, 0x2, 0x19, 0x79, 0x3, 0x2, 0x2, 0x2, 0x1b,
0x7b, 0x3, 0x2, 0x2, 0x2, 0x1d, 0x80, 0x3, 0x2, 0x2, 0x2, 0x1f, 0x83,
0x3, 0x2, 0x2, 0x2, 0x21, 0x88, 0x3, 0x2, 0x2, 0x2, 0x23, 0x8e, 0x3,
0x2, 0x2, 0x2, 0x25, 0x94, 0x3, 0x2, 0x2, 0x2, 0x27, 0x9d, 0x3, 0x2,
0x2, 0x2, 0x29, 0xa4, 0x3, 0x2, 0x2, 0x2, 0x2b, 0xa6, 0x3, 0x2, 0x2,
0x2, 0x2d, 0xa8, 0x3, 0x2, 0x2, 0x2, 0x2f, 0xaa, 0x3, 0x2, 0x2, 0x2,
0x31, 0xac, 0x3, 0x2, 0x2, 0x2, 0x33, 0xae, 0x3, 0x2, 0x2, 0x2, 0x35,
0xb0, 0x3, 0x2, 0x2, 0x2, 0x37, 0xb2, 0x3, 0x2, 0x2, 0x2, 0x39, 0xb4,
0x3, 0x2, 0x2, 0x2, 0x3b, 0xb7, 0x3, 0x2, 0x2, 0x2, 0x3d, 0xba, 0x3,
0x2, 0x2, 0x2, 0x3f, 0xbd, 0x3, 0x2, 0x2, 0x2, 0x41, 0xc0, 0x3, 0x2,
0x2, 0x2, 0x43, 0xc3, 0x3, 0x2, 0x2, 0x2, 0x45, 0xc6, 0x3, 0x2, 0x2,
0x2, 0x47, 0xc8, 0x3, 0x2, 0x2, 0x2, 0x49, 0xca, 0x3, 0x2, 0x2, 0x2,
0x4b, 0xd3, 0x3, 0x2, 0x2, 0x2, 0x4d, 0x11c, 0x3, 0x2, 0x2, 0x2, 0x4f,
0x137, 0x3, 0x2, 0x2, 0x2, 0x51, 0x139, 0x3, 0x2, 0x2, 0x2, 0x53, 0x141,
0x3, 0x2, 0x2, 0x2, 0x55, 0x147, 0x3, 0x2, 0x2, 0x2, 0x57, 0x152, 0x3,
0x2, 0x2, 0x2, 0x59, 0x5a, 0x7, 0x65, 0x2, 0x2, 0x5a, 0x5b, 0x7, 0x71,
0x2, 0x2, 0x5b, 0x5c, 0x7, 0x70, 0x2, 0x2, 0x5c, 0x5d, 0x7, 0x75, 0x2,
0x2, 0x5d, 0x5e, 0x7, 0x76, 0x2, 0x2, 0x5e, 0x4, 0x3, 0x2, 0x2, 0x2,
0x5f, 0x60, 0x7, 0x2e, 0x2, 0x2, 0x60, 0x6, 0x3, 0x2, 0x2, 0x2, 0x61,
0x62, 0x7, 0x3d, 0x2, 0x2, 0x62, 0x8, 0x3, 0x2, 0x2, 0x2, 0x63, 0x64,
0x7, 0x6b, 0x2, 0x2, 0x64, 0x65, 0x7, 0x70, 0x2, 0x2, 0x65, 0x66, 0x7,
0x76, 0x2, 0x2, 0x66, 0xa, 0x3, 0x2, 0x2, 0x2, 0x67, 0x68, 0x7, 0x68,
0x2, 0x2, 0x68, 0x69, 0x7, 0x6e, 0x2, 0x2, 0x69, 0x6a, 0x7, 0x71, 0x2,
0x2, 0x6a, 0x6b, 0x7, 0x63, 0x2, 0x2, 0x6b, 0x6c, 0x7, 0x76, 0x2, 0x2,
0x6c, 0xc, 0x3, 0x2, 0x2, 0x2, 0x6d, 0x6e, 0x7, 0x5d, 0x2, 0x2, 0x6e,
0xe, 0x3, 0x2, 0x2, 0x2, 0x6f, 0x70, 0x7, 0x5f, 0x2, 0x2, 0x70, 0x10,
0x3, 0x2, 0x2, 0x2, 0x71, 0x72, 0x7, 0x3f, 0x2, 0x2, 0x72, 0x12, 0x3,
0x2, 0x2, 0x2, 0x73, 0x74, 0x7, 0x7d, 0x2, 0x2, 0x74, 0x14, 0x3, 0x2,
0x2, 0x2, 0x75, 0x76, 0x7, 0x7f, 0x2, 0x2, 0x76, 0x16, 0x3, 0x2, 0x2,
0x2, 0x77, 0x78, 0x7, 0x2a, 0x2, 0x2, 0x78, 0x18, 0x3, 0x2, 0x2, 0x2,
0x79, 0x7a, 0x7, 0x2b, 0x2, 0x2, 0x7a, 0x1a, 0x3, 0x2, 0x2, 0x2, 0x7b,
0x7c, 0x7, 0x78, 0x2, 0x2, 0x7c, 0x7d, 0x7, 0x71, 0x2, 0x2, 0x7d, 0x7e,
0x7, 0x6b, 0x2, 0x2, 0x7e, 0x7f, 0x7, 0x66, 0x2, 0x2, 0x7f, 0x1c, 0x3,
0x2, 0x2, 0x2, 0x80, 0x81, 0x7, 0x6b, 0x2, 0x2, 0x81, 0x82, 0x7, 0x68,
0x2, 0x2, 0x82, 0x1e, 0x3, 0x2, 0x2, 0x2, 0x83, 0x84, 0x7, 0x67, 0x2,
0x2, 0x84, 0x85, 0x7, 0x6e, 0x2, 0x2, 0x85, 0x86, 0x7, 0x75, 0x2, 0x2,
0x86, 0x87, 0x7, 0x67, 0x2, 0x2, 0x87, 0x20, 0x3, 0x2, 0x2, 0x2, 0x88,
0x89, 0x7, 0x79, 0x2, 0x2, 0x89, 0x8a, 0x7, 0x6a, 0x2, 0x2, 0x8a, 0x8b,
0x7, 0x6b, 0x2, 0x2, 0x8b, 0x8c, 0x7, 0x6e, 0x2, 0x2, 0x8c, 0x8d, 0x7,
0x67, 0x2, 0x2, 0x8d, 0x22, 0x3, 0x2, 0x2, 0x2, 0x8e, 0x8f, 0x7, 0x64,
0x2, 0x2, 0x8f, 0x90, 0x7, 0x74, 0x2, 0x2, 0x90, 0x91, 0x7, 0x67, 0x2,
0x2, 0x91, 0x92, 0x7, 0x63, 0x2, 0x2, 0x92, 0x93, 0x7, 0x6d, 0x2, 0x2,
0x93, 0x24, 0x3, 0x2, 0x2, 0x2, 0x94, 0x95, 0x7, 0x65, 0x2, 0x2, 0x95,
0x96, 0x7, 0x71, 0x2, 0x2, 0x96, 0x97, 0x7, 0x70, 0x2, 0x2, 0x97, 0x98,
0x7, 0x76, 0x2, 0x2, 0x98, 0x99, 0x7, 0x6b, 0x2, 0x2, 0x99, 0x9a, 0x7,
0x70, 0x2, 0x2, 0x9a, 0x9b, 0x7, 0x77, 0x2, 0x2, 0x9b, 0x9c, 0x7, 0x67,
0x2, 0x2, 0x9c, 0x26, 0x3, 0x2, 0x2, 0x2, 0x9d, 0x9e, 0x7, 0x74, 0x2,
0x2, 0x9e, 0x9f, 0x7, 0x67, 0x2, 0x2, 0x9f, 0xa0, 0x7, 0x76, 0x2, 0x2,
0xa0, 0xa1, 0x7, 0x77, 0x2, 0x2, 0xa1, 0xa2, 0x7, 0x74, 0x2, 0x2, 0xa2,
0xa3, 0x7, 0x70, 0x2, 0x2, 0xa3, 0x28, 0x3, 0x2, 0x2, 0x2, 0xa4, 0xa5,
0x7, 0x2d, 0x2, 0x2, 0xa5, 0x2a, 0x3, 0x2, 0x2, 0x2, 0xa6, 0xa7, 0x7,
0x2f, 0x2, 0x2, 0xa7, 0x2c, 0x3, 0x2, 0x2, 0x2, 0xa8, 0xa9, 0x7, 0x23,
0x2, 0x2, 0xa9, 0x2e, 0x3, 0x2, 0x2, 0x2, 0xaa, 0xab, 0x7, 0x2c, 0x2,
0x2, 0xab, 0x30, 0x3, 0x2, 0x2, 0x2, 0xac, 0xad, 0x7, 0x31, 0x2, 0x2,
0xad, 0x32, 0x3, 0x2, 0x2, 0x2, 0xae, 0xaf, 0x7, 0x27, 0x2, 0x2, 0xaf,
0x34, 0x3, 0x2, 0x2, 0x2, 0xb0, 0xb1, 0x7, 0x3e, 0x2, 0x2, 0xb1, 0x36,
0x3, 0x2, 0x2, 0x2, 0xb2, 0xb3, 0x7, 0x40, 0x2, 0x2, 0xb3, 0x38, 0x3,
0x2, 0x2, 0x2, 0xb4, 0xb5, 0x7, 0x3e, 0x2, 0x2, 0xb5, 0xb6, 0x7, 0x3f,
0x2, 0x2, 0xb6, 0x3a, 0x3, 0x2, 0x2, 0x2, 0xb7, 0xb8, 0x7, 0x40, 0x2,
0x2, 0xb8, 0xb9, 0x7, 0x3f, 0x2, 0x2, 0xb9, 0x3c, 0x3, 0x2, 0x2, 0x2,
0xba, 0xbb, 0x7, 0x3f, 0x2, 0x2, 0xbb, 0xbc, 0x7, 0x3f, 0x2, 0x2, 0xbc,
0x3e, 0x3, 0x2, 0x2, 0x2, 0xbd, 0xbe, 0x7, 0x23, 0x2, 0x2, 0xbe, 0xbf,
0x7, 0x3f, 0x2, 0x2, 0xbf, 0x40, 0x3, 0x2, 0x2, 0x2, 0xc0, 0xc1, 0x7,
0x28, 0x2, 0x2, 0xc1, 0xc2, 0x7, 0x28, 0x2, 0x2, 0xc2, 0x42, 0x3, 0x2,
0x2, 0x2, 0xc3, 0xc4, 0x7, 0x7e, 0x2, 0x2, 0xc4, 0xc5, 0x7, 0x7e, 0x2,
0x2, 0xc5, 0x44, 0x3, 0x2, 0x2, 0x2, 0xc6, 0xc7, 0x9, 0x2, 0x2, 0x2,
0xc7, 0x46, 0x3, 0x2, 0x2, 0x2, 0xc8, 0xc9, 0x9, 0x3, 0x2, 0x2, 0xc9,
0x48, 0x3, 0x2, 0x2, 0x2, 0xca, 0xcc, 0x9, 0x4, 0x2, 0x2, 0xcb, 0xcd,
0x9, 0x5, 0x2, 0x2, 0xcc, 0xcb, 0x3, 0x2, 0x2, 0x2, 0xcc, 0xcd, 0x3,
0x2, 0x2, 0x2, 0xcd, 0xcf, 0x3, 0x2, 0x2, 0x2, 0xce, 0xd0, 0x5, 0x45,
0x23, 0x2, 0xcf, 0xce, 0x3, 0x2, 0x2, 0x2, 0xd0, 0xd1, 0x3, 0x2, 0x2,
0x2, 0xd1, 0xcf, 0x3, 0x2, 0x2, 0x2, 0xd1, 0xd2, 0x3, 0x2, 0x2, 0x2,
0xd2, 0x4a, 0x3, 0x2, 0x2, 0x2, 0xd3, 0xd5, 0x9, 0x6, 0x2, 0x2, 0xd4,
0xd6, 0x9, 0x5, 0x2, 0x2, 0xd5, 0xd4, 0x3, 0x2, 0x2, 0x2, 0xd5, 0xd6,
0x3, 0x2, 0x2, 0x2, 0xd6, 0xd8, 0x3, 0x2, 0x2, 0x2, 0xd7, 0xd9, 0x5,
0x45, 0x23, 0x2, 0xd8, 0xd7, 0x3, 0x2, 0x2, 0x2, 0xd9, 0xda, 0x3, 0x2,
0x2, 0x2, 0xda, 0xd8, 0x3, 0x2, 0x2, 0x2, 0xda, 0xdb, 0x3, 0x2, 0x2,
0x2, 0xdb, 0x4c, 0x3, 0x2, 0x2, 0x2, 0xdc, 0xdd, 0x7, 0x32, 0x2, 0x2,
0xdd, 0xe1, 0x7, 0x7a, 0x2, 0x2, 0xde, 0xdf, 0x7, 0x32, 0x2, 0x2, 0xdf,
0xe1, 0x7, 0x5a, 0x2, 0x2, 0xe0, 0xdc, 0x3, 0x2, 0x2, 0x2, 0xe0, 0xde,
0x3, 0x2, 0x2, 0x2, 0xe1, 0xf9, 0x3, 0x2, 0x2, 0x2, 0xe2, 0xe4, 0x5,
0x47, 0x24, 0x2, 0xe3, 0xe2, 0x3, 0x2, 0x2, 0x2, 0xe4, 0xe5, 0x3, 0x2,
0x2, 0x2, 0xe5, 0xe3, 0x3, 0x2, 0x2, 0x2, 0xe5, 0xe6, 0x3, 0x2, 0x2,
0x2, 0xe6, 0xe7, 0x3, 0x2, 0x2, 0x2, 0xe7, 0xeb, 0x7, 0x30, 0x2, 0x2,
0xe8, 0xea, 0x5, 0x47, 0x24, 0x2, 0xe9, 0xe8, 0x3, 0x2, 0x2, 0x2, 0xea,
0xed, 0x3, 0x2, 0x2, 0x2, 0xeb, 0xe9, 0x3, 0x2, 0x2, 0x2, 0xeb, 0xec,
0x3, 0x2, 0x2, 0x2, 0xec, 0xfa, 0x3, 0x2, 0x2, 0x2, 0xed, 0xeb, 0x3,
0x2, 0x2, 0x2, 0xee, 0xf0, 0x7, 0x30, 0x2, 0x2, 0xef, 0xf1, 0x5, 0x47,
0x24, 0x2, 0xf0, 0xef, 0x3, 0x2, 0x2, 0x2, 0xf1, 0xf2, 0x3, 0x2, 0x2,
0x2, 0xf2, 0xf0, 0x3, 0x2, 0x2, 0x2, 0xf2, 0xf3, 0x3, 0x2, 0x2, 0x2,
0xf3, 0xfa, 0x3, 0x2, 0x2, 0x2, 0xf4, 0xf6, 0x5, 0x47, 0x24, 0x2, 0xf5,
0xf4, 0x3, 0x2, 0x2, 0x2, 0xf6, 0xf7, 0x3, 0x2, 0x2, 0x2, 0xf7, 0xf5,
0x3, 0x2, 0x2, 0x2, 0xf7, 0xf8, 0x3, 0x2, 0x2, 0x2, 0xf8, 0xfa, 0x3,
0x2, 0x2, 0x2, 0xf9, 0xe3, 0x3, 0x2, 0x2, 0x2, 0xf9, 0xee, 0x3, 0x2,
0x2, 0x2, 0xf9, 0xf5, 0x3, 0x2, 0x2, 0x2, 0xfa, 0xfb, 0x3, 0x2, 0x2,
0x2, 0xfb, 0xfc, 0x5, 0x4b, 0x26, 0x2, 0xfc, 0x11d, 0x3, 0x2, 0x2, 0x2,
0xfd, 0xff, 0x7, 0x30, 0x2, 0x2, 0xfe, 0x100, 0x5, 0x45, 0x23, 0x2,
0xff, 0xfe, 0x3, 0x2, 0x2, 0x2, 0x100, 0x101, 0x3, 0x2, 0x2, 0x2, 0x101,
0xff, 0x3, 0x2, 0x2, 0x2, 0x101, 0x102, 0x3, 0x2, 0x2, 0x2, 0x102, 0x104,
0x3, 0x2, 0x2, 0x2, 0x103, 0x105, 0x5, 0x49, 0x25, 0x2, 0x104, 0x103,
0x3, 0x2, 0x2, 0x2, 0x104, 0x105, 0x3, 0x2, 0x2, 0x2, 0x105, 0x11d,
0x3, 0x2, 0x2, 0x2, 0x106, 0x108, 0x5, 0x45, 0x23, 0x2, 0x107, 0x106,
0x3, 0x2, 0x2, 0x2, 0x108, 0x109, 0x3, 0x2, 0x2, 0x2, 0x109, 0x107,
0x3, 0x2, 0x2, 0x2, 0x109, 0x10a, 0x3, 0x2, 0x2, 0x2, 0x10a, 0x10b,
0x3, 0x2, 0x2, 0x2, 0x10b, 0x10f, 0x7, 0x30, 0x2, 0x2, 0x10c, 0x10e,
0x5, 0x45, 0x23, 0x2, 0x10d, 0x10c, 0x3, 0x2, 0x2, 0x2, 0x10e, 0x111,
0x3, 0x2, 0x2, 0x2, 0x10f, 0x10d, 0x3, 0x2, 0x2, 0x2, 0x10f, 0x110,
0x3, 0x2, 0x2, 0x2, 0x110, 0x113, 0x3, 0x2, 0x2, 0x2, 0x111, 0x10f,
0x3, 0x2, 0x2, 0x2, 0x112, 0x114, 0x5, 0x49, 0x25, 0x2, 0x113, 0x112,
0x3, 0x2, 0x2, 0x2, 0x113, 0x114, 0x3, 0x2, 0x2, 0x2, 0x114, 0x11d,
0x3, 0x2, 0x2, 0x2, 0x115, 0x117, 0x5, 0x45, 0x23, 0x2, 0x116, 0x115,
0x3, 0x2, 0x2, 0x2, 0x117, 0x118, 0x3, 0x2, 0x2, 0x2, 0x118, 0x116,
0x3, 0x2, 0x2, 0x2, 0x118, 0x119, 0x3, 0x2, 0x2, 0x2, 0x119, 0x11a,
0x3, 0x2, 0x2, 0x2, 0x11a, 0x11b, 0x5, 0x49, 0x25, 0x2, 0x11b, 0x11d,
0x3, 0x2, 0x2, 0x2, 0x11c, 0xe0, 0x3, 0x2, 0x2, 0x2, 0x11c, 0xfd, 0x3,
0x2, 0x2, 0x2, 0x11c, 0x107, 0x3, 0x2, 0x2, 0x2, 0x11c, 0x116, 0x3,
0x2, 0x2, 0x2, 0x11d, 0x4e, 0x3, 0x2, 0x2, 0x2, 0x11e, 0x138, 0x7, 0x32,
0x2, 0x2, 0x11f, 0x123, 0x9, 0x7, 0x2, 0x2, 0x120, 0x122, 0x9, 0x2,
0x2, 0x2, 0x121, 0x120, 0x3, 0x2, 0x2, 0x2, 0x122, 0x125, 0x3, 0x2,
0x2, 0x2, 0x123, 0x121, 0x3, 0x2, 0x2, 0x2, 0x123, 0x124, 0x3, 0x2,
0x2, 0x2, 0x124, 0x138, 0x3, 0x2, 0x2, 0x2, 0x125, 0x123, 0x3, 0x2,
0x2, 0x2, 0x126, 0x128, 0x7, 0x32, 0x2, 0x2, 0x127, 0x129, 0x9, 0x8,
0x2, 0x2, 0x128, 0x127, 0x3, 0x2, 0x2, 0x2, 0x129, 0x12a, 0x3, 0x2,
0x2, 0x2, 0x12a, 0x128, 0x3, 0x2, 0x2, 0x2, 0x12a, 0x12b, 0x3, 0x2,
0x2, 0x2, 0x12b, 0x138, 0x3, 0x2, 0x2, 0x2, 0x12c, 0x12d, 0x7, 0x32,
0x2, 0x2, 0x12d, 0x131, 0x7, 0x7a, 0x2, 0x2, 0x12e, 0x12f, 0x7, 0x32,
0x2, 0x2, 0x12f, 0x131, 0x7, 0x5a, 0x2, 0x2, 0x130, 0x12c, 0x3, 0x2,
0x2, 0x2, 0x130, 0x12e, 0x3, 0x2, 0x2, 0x2, 0x131, 0x133, 0x3, 0x2,
0x2, 0x2, 0x132, 0x134, 0x9, 0x3, 0x2, 0x2, 0x133, 0x132, 0x3, 0x2,
0x2, 0x2, 0x134, 0x135, 0x3, 0x2, 0x2, 0x2, 0x135, 0x133, 0x3, 0x2,
0x2, 0x2, 0x135, 0x136, 0x3, 0x2, 0x2, 0x2, 0x136, 0x138, 0x3, 0x2,
0x2, 0x2, 0x137, 0x11e, 0x3, 0x2, 0x2, 0x2, 0x137, 0x11f, 0x3, 0x2,
0x2, 0x2, 0x137, 0x126, 0x3, 0x2, 0x2, 0x2, 0x137, 0x130, 0x3, 0x2,
0x2, 0x2, 0x138, 0x50, 0x3, 0x2, 0x2, 0x2, 0x139, 0x13d, 0x9, 0x9, 0x2,
0x2, 0x13a, 0x13c, 0x9, 0xa, 0x2, 0x2, 0x13b, 0x13a, 0x3, 0x2, 0x2,
0x2, 0x13c, 0x13f, 0x3, 0x2, 0x2, 0x2, 0x13d, 0x13b, 0x3, 0x2, 0x2,
0x2, 0x13d, 0x13e, 0x3, 0x2, 0x2, 0x2, 0x13e, 0x52, 0x3, 0x2, 0x2, 0x2,
0x13f, 0x13d, 0x3, 0x2, 0x2, 0x2, 0x140, 0x142, 0x9, 0xb, 0x2, 0x2,
0x141, 0x140, 0x3, 0x2, 0x2, 0x2, 0x142, 0x143, 0x3, 0x2, 0x2, 0x2,
0x143, 0x141, 0x3, 0x2, 0x2, 0x2, 0x143, 0x144, 0x3, 0x2, 0x2, 0x2,
0x144, 0x145, 0x3, 0x2, 0x2, 0x2, 0x145, 0x146, 0x8, 0x2a, 0x2, 0x2,
0x146, 0x54, 0x3, 0x2, 0x2, 0x2, 0x147, 0x148, 0x7, 0x31, 0x2, 0x2,
0x148, 0x149, 0x7, 0x31, 0x2, 0x2, 0x149, 0x14d, 0x3, 0x2, 0x2, 0x2,
0x14a, 0x14c, 0xa, 0xc, 0x2, 0x2, 0x14b, 0x14a, 0x3, 0x2, 0x2, 0x2,
0x14c, 0x14f, 0x3, 0x2, 0x2, 0x2, 0x14d, 0x14b, 0x3, 0x2, 0x2, 0x2,
0x14d, 0x14e, 0x3, 0x2, 0x2, 0x2, 0x14e, 0x150, 0x3, 0x2, 0x2, 0x2,
0x14f, 0x14d, 0x3, 0x2, 0x2, 0x2, 0x150, 0x151, 0x8, 0x2b, 0x2, 0x2,
0x151, 0x56, 0x3, 0x2, 0x2, 0x2, 0x152, 0x153, 0x7, 0x31, 0x2, 0x2,
0x153, 0x154, 0x7, 0x2c, 0x2, 0x2, 0x154, 0x158, 0x3, 0x2, 0x2, 0x2,
0x155, 0x157, 0xb, 0x2, 0x2, 0x2, 0x156, 0x155, 0x3, 0x2, 0x2, 0x2,
0x157, 0x15a, 0x3, 0x2, 0x2, 0x2, 0x158, 0x159, 0x3, 0x2, 0x2, 0x2,
0x158, 0x156, 0x3, 0x2, 0x2, 0x2, 0x159, 0x15b, 0x3, 0x2, 0x2, 0x2,
0x15a, 0x158, 0x3, 0x2, 0x2, 0x2, 0x15b, 0x15c, 0x7, 0x2c, 0x2, 0x2,
0x15c, 0x15d, 0x7, 0x31, 0x2, 0x2, 0x15d, 0x15e, 0x3, 0x2, 0x2, 0x2,
0x15e, 0x15f, 0x8, 0x2c, 0x2, 0x2, 0x15f, 0x58, 0x3, 0x2, 0x2, 0x2,
0x1d, 0x2, 0xcc, 0xd1, 0xd5, 0xda, 0xe0, 0xe5, 0xeb, 0xf2, 0xf7, 0xf9,
0x101, 0x104, 0x109, 0x10f, 0x113, 0x118, 0x11c, 0x123, 0x12a, 0x130,
0x135, 0x137, 0x13d, 0x143, 0x14d, 0x158, 0x3, 0x8, 0x2, 0x2,
};
atn::ATNDeserializer deserializer;
_atn = deserializer.deserialize(_serializedATN);
size_t count = _atn.getNumberOfDecisions(); void SysYLexer::initialize() {
_decisionToDFA.reserve(count); #if ANTLR4_USE_THREAD_LOCAL_CACHE
for (size_t i = 0; i < count; i++) { sysylexerLexerInitialize();
_decisionToDFA.emplace_back(_atn.getDecisionState(i), i); #else
::antlr4::internal::call_once(sysylexerLexerOnceFlag, sysylexerLexerInitialize);
#endif
} }
}
SysYLexer::Initializer SysYLexer::_init;

@ -1,5 +1,5 @@
// Generated from SysY.g4 by ANTLR 4.7.2 // Generated from SysY.g4 by ANTLR 4.13.2
#pragma once #pragma once
@ -12,51 +12,43 @@
class SysYLexer : public antlr4::Lexer { class SysYLexer : public antlr4::Lexer {
public: public:
enum { enum {
T__0 = 1, T__1 = 2, T__2 = 3, T__3 = 4, T__4 = 5, T__5 = 6, T__6 = 7, CONST = 1, INT = 2, FLOAT = 3, VOID = 4, IF = 5, ELSE = 6, WHILE = 7,
T__7 = 8, T__8 = 9, T__9 = 10, T__10 = 11, T__11 = 12, T__12 = 13, T__13 = 14, BREAK = 8, CONTINUE = 9, RETURN = 10, ASSIGN = 11, EQ = 12, NE = 13,
T__14 = 15, T__15 = 16, T__16 = 17, T__17 = 18, T__18 = 19, T__19 = 20, LT = 14, GT = 15, LE = 16, GE = 17, ADD = 18, SUB = 19, MUL = 20, DIV = 21,
T__20 = 21, T__21 = 22, T__22 = 23, T__23 = 24, T__24 = 25, T__25 = 26, MOD = 22, NOT = 23, AND = 24, OR = 25, LPAREN = 26, RPAREN = 27, LBRACK = 28,
T__26 = 27, T__27 = 28, T__28 = 29, T__29 = 30, T__30 = 31, T__31 = 32, RBRACK = 29, LBRACE = 30, RBRACE = 31, COMMA = 32, SEMICOLON = 33, ID = 34,
T__32 = 33, FloatConst = 34, IntConst = 35, Ident = 36, WS = 37, LINE_COMMENT = 38, FLITERAL = 35, ILITERAL = 36, WS = 37, LINECOMMENT = 38, BLOCKCOMMENT = 39
BLOCK_COMMENT = 39
}; };
SysYLexer(antlr4::CharStream *input); explicit SysYLexer(antlr4::CharStream *input);
~SysYLexer();
virtual std::string getGrammarFileName() const override; ~SysYLexer() override;
virtual const std::vector<std::string>& getRuleNames() const override;
virtual const std::vector<std::string>& getChannelNames() const override;
virtual const std::vector<std::string>& getModeNames() const override;
virtual const std::vector<std::string>& getTokenNames() const override; // deprecated, use vocabulary instead
virtual antlr4::dfa::Vocabulary& getVocabulary() const override;
virtual const std::vector<uint16_t> getSerializedATN() const override; std::string getGrammarFileName() const override;
virtual const antlr4::atn::ATN& getATN() const override;
private: const std::vector<std::string>& getRuleNames() const override;
static std::vector<antlr4::dfa::DFA> _decisionToDFA;
static antlr4::atn::PredictionContextCache _sharedContextCache; const std::vector<std::string>& getChannelNames() const override;
static std::vector<std::string> _ruleNames;
static std::vector<std::string> _tokenNames; const std::vector<std::string>& getModeNames() const override;
static std::vector<std::string> _channelNames;
static std::vector<std::string> _modeNames; const antlr4::dfa::Vocabulary& getVocabulary() const override;
static std::vector<std::string> _literalNames; antlr4::atn::SerializedATNView getSerializedATN() const override;
static std::vector<std::string> _symbolicNames;
static antlr4::dfa::Vocabulary _vocabulary;
static antlr4::atn::ATN _atn;
static std::vector<uint16_t> _serializedATN;
const antlr4::atn::ATN& getATN() const override;
// By default the static state used to implement the lexer is lazily initialized during the first
// call to the constructor. You can call this function if you wish to initialize the static state
// ahead of time.
static void initialize();
private:
// Individual action functions triggered by action() above. // Individual action functions triggered by action() above.
// Individual semantic predicate functions triggered by sempred() above. // Individual semantic predicate functions triggered by sempred() above.
struct Initializer {
Initializer();
};
static Initializer _init;
}; };

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
// Generated from SysY.g4 by ANTLR 4.7.2 // Generated from SysY.g4 by ANTLR 4.13.2
#pragma once #pragma once
@ -12,55 +12,62 @@
class SysYParser : public antlr4::Parser { class SysYParser : public antlr4::Parser {
public: public:
enum { enum {
T__0 = 1, T__1 = 2, T__2 = 3, T__3 = 4, T__4 = 5, T__5 = 6, T__6 = 7, CONST = 1, INT = 2, FLOAT = 3, VOID = 4, IF = 5, ELSE = 6, WHILE = 7,
T__7 = 8, T__8 = 9, T__9 = 10, T__10 = 11, T__11 = 12, T__12 = 13, T__13 = 14, BREAK = 8, CONTINUE = 9, RETURN = 10, ASSIGN = 11, EQ = 12, NE = 13,
T__14 = 15, T__15 = 16, T__16 = 17, T__17 = 18, T__18 = 19, T__19 = 20, LT = 14, GT = 15, LE = 16, GE = 17, ADD = 18, SUB = 19, MUL = 20, DIV = 21,
T__20 = 21, T__21 = 22, T__22 = 23, T__23 = 24, T__24 = 25, T__25 = 26, MOD = 22, NOT = 23, AND = 24, OR = 25, LPAREN = 26, RPAREN = 27, LBRACK = 28,
T__26 = 27, T__27 = 28, T__28 = 29, T__29 = 30, T__30 = 31, T__31 = 32, RBRACK = 29, LBRACE = 30, RBRACE = 31, COMMA = 32, SEMICOLON = 33, ID = 34,
T__32 = 33, FloatConst = 34, IntConst = 35, Ident = 36, WS = 37, LINE_COMMENT = 38, FLITERAL = 35, ILITERAL = 36, WS = 37, LINECOMMENT = 38, BLOCKCOMMENT = 39
BLOCK_COMMENT = 39
}; };
enum { enum {
RuleCompUnit = 0, RuleDecl = 1, RuleConstDecl = 2, RuleBType = 3, RuleConstDef = 4, RuleCompUnit = 0, RuleDecl = 1, RuleConstDecl = 2, RuleConstDef = 3,
RuleConstInitVal = 5, RuleVarDecl = 6, RuleVarDef = 7, RuleInitVal = 8, RuleConstInitValue = 4, RuleVarDecl = 5, RuleBtype = 6, RuleVarDef = 7,
RuleFuncDef = 9, RuleFuncType = 10, RuleFuncFParams = 11, RuleFuncFParam = 12, RuleInitValue = 8, RuleFuncDef = 9, RuleFuncType = 10, RuleFuncFParams = 11,
RuleBlock = 13, RuleBlockItem = 14, RuleStmt = 15, RuleExp = 16, RuleCond = 17, RuleFuncFParam = 12, RuleBlockStmt = 13, RuleBlockItem = 14, RuleStmt = 15,
RuleLVal = 18, RulePrimaryExp = 19, RuleNumber = 20, RuleUnaryExp = 21, RuleReturnStmt = 16, RuleExp = 17, RuleCond = 18, RuleLValue = 19, RulePrimaryExp = 20,
RuleUnaryOp = 22, RuleFuncRParams = 23, RuleMulExp = 24, RuleAddExp = 25, RuleNumber = 21, RuleUnaryExp = 22, RuleUnaryOp = 23, RuleFuncRParams = 24,
RuleRelExp = 26, RuleEqExp = 27, RuleLAndExp = 28, RuleLOrExp = 29, RuleMulExp = 25, RuleAddExp = 26, RuleRelExp = 27, RuleEqExp = 28, RuleLAndExp = 29,
RuleConstExp = 30 RuleLOrExp = 30, RuleConstExp = 31
}; };
SysYParser(antlr4::TokenStream *input); explicit SysYParser(antlr4::TokenStream *input);
~SysYParser();
virtual std::string getGrammarFileName() const override; SysYParser(antlr4::TokenStream *input, const antlr4::atn::ParserATNSimulatorOptions &options);
virtual const antlr4::atn::ATN& getATN() const override { return _atn; };
virtual const std::vector<std::string>& getTokenNames() const override { return _tokenNames; }; // deprecated: use vocabulary instead. ~SysYParser() override;
virtual const std::vector<std::string>& getRuleNames() const override;
virtual antlr4::dfa::Vocabulary& getVocabulary() const override; std::string getGrammarFileName() const override;
const antlr4::atn::ATN& getATN() const override;
const std::vector<std::string>& getRuleNames() const override;
const antlr4::dfa::Vocabulary& getVocabulary() const override;
antlr4::atn::SerializedATNView getSerializedATN() const override;
class CompUnitContext; class CompUnitContext;
class DeclContext; class DeclContext;
class ConstDeclContext; class ConstDeclContext;
class BTypeContext;
class ConstDefContext; class ConstDefContext;
class ConstInitValContext; class ConstInitValueContext;
class VarDeclContext; class VarDeclContext;
class BtypeContext;
class VarDefContext; class VarDefContext;
class InitValContext; class InitValueContext;
class FuncDefContext; class FuncDefContext;
class FuncTypeContext; class FuncTypeContext;
class FuncFParamsContext; class FuncFParamsContext;
class FuncFParamContext; class FuncFParamContext;
class BlockContext; class BlockStmtContext;
class BlockItemContext; class BlockItemContext;
class StmtContext; class StmtContext;
class ReturnStmtContext;
class ExpContext; class ExpContext;
class CondContext; class CondContext;
class LValContext; class LValueContext;
class PrimaryExpContext; class PrimaryExpContext;
class NumberContext; class NumberContext;
class UnaryExpContext; class UnaryExpContext;
@ -78,12 +85,14 @@ public:
public: public:
CompUnitContext(antlr4::ParserRuleContext *parent, size_t invokingState); CompUnitContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *EOF();
std::vector<DeclContext *> decl(); std::vector<DeclContext *> decl();
DeclContext* decl(size_t i); DeclContext* decl(size_t i);
std::vector<FuncDefContext *> funcDef(); std::vector<FuncDefContext *> funcDef();
FuncDefContext* funcDef(size_t i); FuncDefContext* funcDef(size_t i);
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -96,7 +105,8 @@ public:
ConstDeclContext *constDecl(); ConstDeclContext *constDecl();
VarDeclContext *varDecl(); VarDeclContext *varDecl();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -106,109 +116,146 @@ public:
public: public:
ConstDeclContext(antlr4::ParserRuleContext *parent, size_t invokingState); ConstDeclContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
BTypeContext *bType(); antlr4::tree::TerminalNode *CONST();
BtypeContext *btype();
std::vector<ConstDefContext *> constDef(); std::vector<ConstDefContext *> constDef();
ConstDefContext* constDef(size_t i); ConstDefContext* constDef(size_t i);
antlr4::tree::TerminalNode *SEMICOLON();
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
ConstDeclContext* constDecl();
class BTypeContext : public antlr4::ParserRuleContext {
public:
BTypeContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
BTypeContext* bType(); ConstDeclContext* constDecl();
class ConstDefContext : public antlr4::ParserRuleContext { class ConstDefContext : public antlr4::ParserRuleContext {
public: public:
ConstDefContext(antlr4::ParserRuleContext *parent, size_t invokingState); ConstDefContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *Ident(); antlr4::tree::TerminalNode *ID();
ConstInitValContext *constInitVal(); antlr4::tree::TerminalNode *ASSIGN();
ConstInitValueContext *constInitValue();
std::vector<antlr4::tree::TerminalNode *> LBRACK();
antlr4::tree::TerminalNode* LBRACK(size_t i);
std::vector<ConstExpContext *> constExp(); std::vector<ConstExpContext *> constExp();
ConstExpContext* constExp(size_t i); ConstExpContext* constExp(size_t i);
std::vector<antlr4::tree::TerminalNode *> RBRACK();
antlr4::tree::TerminalNode* RBRACK(size_t i);
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
ConstDefContext* constDef(); ConstDefContext* constDef();
class ConstInitValContext : public antlr4::ParserRuleContext { class ConstInitValueContext : public antlr4::ParserRuleContext {
public: public:
ConstInitValContext(antlr4::ParserRuleContext *parent, size_t invokingState); ConstInitValueContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
ConstExpContext *constExp(); ConstExpContext *constExp();
std::vector<ConstInitValContext *> constInitVal(); antlr4::tree::TerminalNode *LBRACE();
ConstInitValContext* constInitVal(size_t i); antlr4::tree::TerminalNode *RBRACE();
std::vector<ConstInitValueContext *> constInitValue();
ConstInitValueContext* constInitValue(size_t i);
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
ConstInitValContext* constInitVal(); ConstInitValueContext* constInitValue();
class VarDeclContext : public antlr4::ParserRuleContext { class VarDeclContext : public antlr4::ParserRuleContext {
public: public:
VarDeclContext(antlr4::ParserRuleContext *parent, size_t invokingState); VarDeclContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
BTypeContext *bType(); BtypeContext *btype();
std::vector<VarDefContext *> varDef(); std::vector<VarDefContext *> varDef();
VarDefContext* varDef(size_t i); VarDefContext* varDef(size_t i);
antlr4::tree::TerminalNode *SEMICOLON();
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
VarDeclContext* varDecl(); VarDeclContext* varDecl();
class BtypeContext : public antlr4::ParserRuleContext {
public:
BtypeContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *INT();
antlr4::tree::TerminalNode *FLOAT();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
BtypeContext* btype();
class VarDefContext : public antlr4::ParserRuleContext { class VarDefContext : public antlr4::ParserRuleContext {
public: public:
VarDefContext(antlr4::ParserRuleContext *parent, size_t invokingState); VarDefContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *Ident(); antlr4::tree::TerminalNode *ID();
std::vector<antlr4::tree::TerminalNode *> LBRACK();
antlr4::tree::TerminalNode* LBRACK(size_t i);
std::vector<ConstExpContext *> constExp(); std::vector<ConstExpContext *> constExp();
ConstExpContext* constExp(size_t i); ConstExpContext* constExp(size_t i);
InitValContext *initVal(); std::vector<antlr4::tree::TerminalNode *> RBRACK();
antlr4::tree::TerminalNode* RBRACK(size_t i);
antlr4::tree::TerminalNode *ASSIGN();
InitValueContext *initValue();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
VarDefContext* varDef(); VarDefContext* varDef();
class InitValContext : public antlr4::ParserRuleContext { class InitValueContext : public antlr4::ParserRuleContext {
public: public:
InitValContext(antlr4::ParserRuleContext *parent, size_t invokingState); InitValueContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
ExpContext *exp(); ExpContext *exp();
std::vector<InitValContext *> initVal(); antlr4::tree::TerminalNode *LBRACE();
InitValContext* initVal(size_t i); antlr4::tree::TerminalNode *RBRACE();
std::vector<InitValueContext *> initValue();
InitValueContext* initValue(size_t i);
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
InitValContext* initVal(); InitValueContext* initValue();
class FuncDefContext : public antlr4::ParserRuleContext { class FuncDefContext : public antlr4::ParserRuleContext {
public: public:
FuncDefContext(antlr4::ParserRuleContext *parent, size_t invokingState); FuncDefContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
FuncTypeContext *funcType(); FuncTypeContext *funcType();
antlr4::tree::TerminalNode *Ident(); antlr4::tree::TerminalNode *ID();
BlockContext *block(); antlr4::tree::TerminalNode *LPAREN();
antlr4::tree::TerminalNode *RPAREN();
BlockStmtContext *blockStmt();
FuncFParamsContext *funcFParams(); FuncFParamsContext *funcFParams();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -218,8 +265,12 @@ public:
public: public:
FuncTypeContext(antlr4::ParserRuleContext *parent, size_t invokingState); FuncTypeContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *INT();
antlr4::tree::TerminalNode *FLOAT();
antlr4::tree::TerminalNode *VOID();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -231,8 +282,11 @@ public:
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
std::vector<FuncFParamContext *> funcFParam(); std::vector<FuncFParamContext *> funcFParam();
FuncFParamContext* funcFParam(size_t i); FuncFParamContext* funcFParam(size_t i);
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -242,29 +296,37 @@ public:
public: public:
FuncFParamContext(antlr4::ParserRuleContext *parent, size_t invokingState); FuncFParamContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
BTypeContext *bType(); BtypeContext *btype();
antlr4::tree::TerminalNode *Ident(); antlr4::tree::TerminalNode *ID();
std::vector<antlr4::tree::TerminalNode *> LBRACK();
antlr4::tree::TerminalNode* LBRACK(size_t i);
std::vector<antlr4::tree::TerminalNode *> RBRACK();
antlr4::tree::TerminalNode* RBRACK(size_t i);
std::vector<ExpContext *> exp(); std::vector<ExpContext *> exp();
ExpContext* exp(size_t i); ExpContext* exp(size_t i);
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
FuncFParamContext* funcFParam(); FuncFParamContext* funcFParam();
class BlockContext : public antlr4::ParserRuleContext { class BlockStmtContext : public antlr4::ParserRuleContext {
public: public:
BlockContext(antlr4::ParserRuleContext *parent, size_t invokingState); BlockStmtContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *LBRACE();
antlr4::tree::TerminalNode *RBRACE();
std::vector<BlockItemContext *> blockItem(); std::vector<BlockItemContext *> blockItem();
BlockItemContext* blockItem(size_t i); BlockItemContext* blockItem(size_t i);
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
BlockContext* block(); BlockStmtContext* blockStmt();
class BlockItemContext : public antlr4::ParserRuleContext { class BlockItemContext : public antlr4::ParserRuleContext {
public: public:
@ -273,7 +335,8 @@ public:
DeclContext *decl(); DeclContext *decl();
StmtContext *stmt(); StmtContext *stmt();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -283,26 +346,53 @@ public:
public: public:
StmtContext(antlr4::ParserRuleContext *parent, size_t invokingState); StmtContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
LValContext *lVal(); LValueContext *lValue();
antlr4::tree::TerminalNode *ASSIGN();
ExpContext *exp(); ExpContext *exp();
BlockContext *block(); antlr4::tree::TerminalNode *SEMICOLON();
BlockStmtContext *blockStmt();
antlr4::tree::TerminalNode *IF();
antlr4::tree::TerminalNode *LPAREN();
CondContext *cond(); CondContext *cond();
antlr4::tree::TerminalNode *RPAREN();
std::vector<StmtContext *> stmt(); std::vector<StmtContext *> stmt();
StmtContext* stmt(size_t i); StmtContext* stmt(size_t i);
antlr4::tree::TerminalNode *ELSE();
antlr4::tree::TerminalNode *WHILE();
antlr4::tree::TerminalNode *BREAK();
antlr4::tree::TerminalNode *CONTINUE();
ReturnStmtContext *returnStmt();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
StmtContext* stmt(); StmtContext* stmt();
class ReturnStmtContext : public antlr4::ParserRuleContext {
public:
ReturnStmtContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *RETURN();
antlr4::tree::TerminalNode *SEMICOLON();
ExpContext *exp();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ReturnStmtContext* returnStmt();
class ExpContext : public antlr4::ParserRuleContext { class ExpContext : public antlr4::ParserRuleContext {
public: public:
ExpContext(antlr4::ParserRuleContext *parent, size_t invokingState); ExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
AddExpContext *addExp(); AddExpContext *addExp();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -314,35 +404,44 @@ public:
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
LOrExpContext *lOrExp(); LOrExpContext *lOrExp();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
CondContext* cond(); CondContext* cond();
class LValContext : public antlr4::ParserRuleContext { class LValueContext : public antlr4::ParserRuleContext {
public: public:
LValContext(antlr4::ParserRuleContext *parent, size_t invokingState); LValueContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *Ident(); antlr4::tree::TerminalNode *ID();
std::vector<antlr4::tree::TerminalNode *> LBRACK();
antlr4::tree::TerminalNode* LBRACK(size_t i);
std::vector<ExpContext *> exp(); std::vector<ExpContext *> exp();
ExpContext* exp(size_t i); ExpContext* exp(size_t i);
std::vector<antlr4::tree::TerminalNode *> RBRACK();
antlr4::tree::TerminalNode* RBRACK(size_t i);
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
LValContext* lVal(); LValueContext* lValue();
class PrimaryExpContext : public antlr4::ParserRuleContext { class PrimaryExpContext : public antlr4::ParserRuleContext {
public: public:
PrimaryExpContext(antlr4::ParserRuleContext *parent, size_t invokingState); PrimaryExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *LPAREN();
ExpContext *exp(); ExpContext *exp();
LValContext *lVal(); antlr4::tree::TerminalNode *RPAREN();
LValueContext *lValue();
NumberContext *number(); NumberContext *number();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -352,10 +451,11 @@ public:
public: public:
NumberContext(antlr4::ParserRuleContext *parent, size_t invokingState); NumberContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *FloatConst(); antlr4::tree::TerminalNode *ILITERAL();
antlr4::tree::TerminalNode *IntConst(); antlr4::tree::TerminalNode *FLITERAL();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -366,12 +466,15 @@ public:
UnaryExpContext(antlr4::ParserRuleContext *parent, size_t invokingState); UnaryExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
PrimaryExpContext *primaryExp(); PrimaryExpContext *primaryExp();
antlr4::tree::TerminalNode *Ident(); antlr4::tree::TerminalNode *ID();
antlr4::tree::TerminalNode *LPAREN();
antlr4::tree::TerminalNode *RPAREN();
FuncRParamsContext *funcRParams(); FuncRParamsContext *funcRParams();
UnaryOpContext *unaryOp(); UnaryOpContext *unaryOp();
UnaryExpContext *unaryExp(); UnaryExpContext *unaryExp();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -381,8 +484,12 @@ public:
public: public:
UnaryOpContext(antlr4::ParserRuleContext *parent, size_t invokingState); UnaryOpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *ADD();
antlr4::tree::TerminalNode *SUB();
antlr4::tree::TerminalNode *NOT();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -394,8 +501,11 @@ public:
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
std::vector<ExpContext *> exp(); std::vector<ExpContext *> exp();
ExpContext* exp(size_t i); ExpContext* exp(size_t i);
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
@ -405,109 +515,127 @@ public:
public: public:
MulExpContext(antlr4::ParserRuleContext *parent, size_t invokingState); MulExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
std::vector<UnaryExpContext *> unaryExp(); UnaryExpContext *unaryExp();
UnaryExpContext* unaryExp(size_t i); MulExpContext *mulExp();
antlr4::tree::TerminalNode *MUL();
antlr4::tree::TerminalNode *DIV();
antlr4::tree::TerminalNode *MOD();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
MulExpContext* mulExp(); MulExpContext* mulExp();
MulExpContext* mulExp(int precedence);
class AddExpContext : public antlr4::ParserRuleContext { class AddExpContext : public antlr4::ParserRuleContext {
public: public:
AddExpContext(antlr4::ParserRuleContext *parent, size_t invokingState); AddExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
std::vector<MulExpContext *> mulExp(); MulExpContext *mulExp();
MulExpContext* mulExp(size_t i); AddExpContext *addExp();
antlr4::tree::TerminalNode *ADD();
antlr4::tree::TerminalNode *SUB();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
AddExpContext* addExp(); AddExpContext* addExp();
AddExpContext* addExp(int precedence);
class RelExpContext : public antlr4::ParserRuleContext { class RelExpContext : public antlr4::ParserRuleContext {
public: public:
RelExpContext(antlr4::ParserRuleContext *parent, size_t invokingState); RelExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
std::vector<AddExpContext *> addExp(); AddExpContext *addExp();
AddExpContext* addExp(size_t i); RelExpContext *relExp();
antlr4::tree::TerminalNode *LT();
antlr4::tree::TerminalNode *GT();
antlr4::tree::TerminalNode *LE();
antlr4::tree::TerminalNode *GE();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
RelExpContext* relExp(); RelExpContext* relExp();
RelExpContext* relExp(int precedence);
class EqExpContext : public antlr4::ParserRuleContext { class EqExpContext : public antlr4::ParserRuleContext {
public: public:
EqExpContext(antlr4::ParserRuleContext *parent, size_t invokingState); EqExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
std::vector<RelExpContext *> relExp(); RelExpContext *relExp();
RelExpContext* relExp(size_t i); EqExpContext *eqExp();
antlr4::tree::TerminalNode *EQ();
antlr4::tree::TerminalNode *NE();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
EqExpContext* eqExp(); EqExpContext* eqExp();
EqExpContext* eqExp(int precedence);
class LAndExpContext : public antlr4::ParserRuleContext { class LAndExpContext : public antlr4::ParserRuleContext {
public: public:
LAndExpContext(antlr4::ParserRuleContext *parent, size_t invokingState); LAndExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
std::vector<EqExpContext *> eqExp(); EqExpContext *eqExp();
EqExpContext* eqExp(size_t i); LAndExpContext *lAndExp();
antlr4::tree::TerminalNode *AND();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
LAndExpContext* lAndExp(); LAndExpContext* lAndExp();
LAndExpContext* lAndExp(int precedence);
class LOrExpContext : public antlr4::ParserRuleContext { class LOrExpContext : public antlr4::ParserRuleContext {
public: public:
LOrExpContext(antlr4::ParserRuleContext *parent, size_t invokingState); LOrExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
std::vector<LAndExpContext *> lAndExp(); LAndExpContext *lAndExp();
LAndExpContext* lAndExp(size_t i); LOrExpContext *lOrExp();
antlr4::tree::TerminalNode *OR();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
LOrExpContext* lOrExp(); LOrExpContext* lOrExp();
LOrExpContext* lOrExp(int precedence);
class ConstExpContext : public antlr4::ParserRuleContext { class ConstExpContext : public antlr4::ParserRuleContext {
public: public:
ConstExpContext(antlr4::ParserRuleContext *parent, size_t invokingState); ConstExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override; virtual size_t getRuleIndex() const override;
AddExpContext *addExp(); AddExpContext *addExp();
virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
}; };
ConstExpContext* constExp(); ConstExpContext* constExp();
private: bool sempred(antlr4::RuleContext *_localctx, size_t ruleIndex, size_t predicateIndex) override;
static std::vector<antlr4::dfa::DFA> _decisionToDFA;
static antlr4::atn::PredictionContextCache _sharedContextCache;
static std::vector<std::string> _ruleNames;
static std::vector<std::string> _tokenNames;
static std::vector<std::string> _literalNames; bool mulExpSempred(MulExpContext *_localctx, size_t predicateIndex);
static std::vector<std::string> _symbolicNames; bool addExpSempred(AddExpContext *_localctx, size_t predicateIndex);
static antlr4::dfa::Vocabulary _vocabulary; bool relExpSempred(RelExpContext *_localctx, size_t predicateIndex);
static antlr4::atn::ATN _atn; bool eqExpSempred(EqExpContext *_localctx, size_t predicateIndex);
static std::vector<uint16_t> _serializedATN; bool lAndExpSempred(LAndExpContext *_localctx, size_t predicateIndex);
bool lOrExpSempred(LOrExpContext *_localctx, size_t predicateIndex);
// By default the static state used to implement the parser is lazily initialized during the first
// call to the constructor. You can call this function if you wish to initialize the static state
// ahead of time.
static void initialize();
struct Initializer { private:
Initializer();
};
static Initializer _init;
}; };

@ -1,5 +1,5 @@
// Generated from SysY.g4 by ANTLR 4.7.2 // Generated from SysY.g4 by ANTLR 4.13.2
#include "SysYVisitor.h" #include "SysYVisitor.h"

@ -1,5 +1,5 @@
// Generated from SysY.g4 by ANTLR 4.7.2 // Generated from SysY.g4 by ANTLR 4.13.2
#pragma once #pragma once
@ -19,67 +19,69 @@ public:
/** /**
* Visit parse trees produced by SysYParser. * Visit parse trees produced by SysYParser.
*/ */
virtual antlrcpp::Any visitCompUnit(SysYParser::CompUnitContext *context) = 0; virtual std::any visitCompUnit(SysYParser::CompUnitContext *context) = 0;
virtual antlrcpp::Any visitDecl(SysYParser::DeclContext *context) = 0; virtual std::any visitDecl(SysYParser::DeclContext *context) = 0;
virtual antlrcpp::Any visitConstDecl(SysYParser::ConstDeclContext *context) = 0; virtual std::any visitConstDecl(SysYParser::ConstDeclContext *context) = 0;
virtual antlrcpp::Any visitBType(SysYParser::BTypeContext *context) = 0; virtual std::any visitConstDef(SysYParser::ConstDefContext *context) = 0;
virtual antlrcpp::Any visitConstDef(SysYParser::ConstDefContext *context) = 0; virtual std::any visitConstInitValue(SysYParser::ConstInitValueContext *context) = 0;
virtual antlrcpp::Any visitConstInitVal(SysYParser::ConstInitValContext *context) = 0; virtual std::any visitVarDecl(SysYParser::VarDeclContext *context) = 0;
virtual antlrcpp::Any visitVarDecl(SysYParser::VarDeclContext *context) = 0; virtual std::any visitBtype(SysYParser::BtypeContext *context) = 0;
virtual antlrcpp::Any visitVarDef(SysYParser::VarDefContext *context) = 0; virtual std::any visitVarDef(SysYParser::VarDefContext *context) = 0;
virtual antlrcpp::Any visitInitVal(SysYParser::InitValContext *context) = 0; virtual std::any visitInitValue(SysYParser::InitValueContext *context) = 0;
virtual antlrcpp::Any visitFuncDef(SysYParser::FuncDefContext *context) = 0; virtual std::any visitFuncDef(SysYParser::FuncDefContext *context) = 0;
virtual antlrcpp::Any visitFuncType(SysYParser::FuncTypeContext *context) = 0; virtual std::any visitFuncType(SysYParser::FuncTypeContext *context) = 0;
virtual antlrcpp::Any visitFuncFParams(SysYParser::FuncFParamsContext *context) = 0; virtual std::any visitFuncFParams(SysYParser::FuncFParamsContext *context) = 0;
virtual antlrcpp::Any visitFuncFParam(SysYParser::FuncFParamContext *context) = 0; virtual std::any visitFuncFParam(SysYParser::FuncFParamContext *context) = 0;
virtual antlrcpp::Any visitBlock(SysYParser::BlockContext *context) = 0; virtual std::any visitBlockStmt(SysYParser::BlockStmtContext *context) = 0;
virtual antlrcpp::Any visitBlockItem(SysYParser::BlockItemContext *context) = 0; virtual std::any visitBlockItem(SysYParser::BlockItemContext *context) = 0;
virtual antlrcpp::Any visitStmt(SysYParser::StmtContext *context) = 0; virtual std::any visitStmt(SysYParser::StmtContext *context) = 0;
virtual antlrcpp::Any visitExp(SysYParser::ExpContext *context) = 0; virtual std::any visitReturnStmt(SysYParser::ReturnStmtContext *context) = 0;
virtual antlrcpp::Any visitCond(SysYParser::CondContext *context) = 0; virtual std::any visitExp(SysYParser::ExpContext *context) = 0;
virtual antlrcpp::Any visitLVal(SysYParser::LValContext *context) = 0; virtual std::any visitCond(SysYParser::CondContext *context) = 0;
virtual antlrcpp::Any visitPrimaryExp(SysYParser::PrimaryExpContext *context) = 0; virtual std::any visitLValue(SysYParser::LValueContext *context) = 0;
virtual antlrcpp::Any visitNumber(SysYParser::NumberContext *context) = 0; virtual std::any visitPrimaryExp(SysYParser::PrimaryExpContext *context) = 0;
virtual antlrcpp::Any visitUnaryExp(SysYParser::UnaryExpContext *context) = 0; virtual std::any visitNumber(SysYParser::NumberContext *context) = 0;
virtual antlrcpp::Any visitUnaryOp(SysYParser::UnaryOpContext *context) = 0; virtual std::any visitUnaryExp(SysYParser::UnaryExpContext *context) = 0;
virtual antlrcpp::Any visitFuncRParams(SysYParser::FuncRParamsContext *context) = 0; virtual std::any visitUnaryOp(SysYParser::UnaryOpContext *context) = 0;
virtual antlrcpp::Any visitMulExp(SysYParser::MulExpContext *context) = 0; virtual std::any visitFuncRParams(SysYParser::FuncRParamsContext *context) = 0;
virtual antlrcpp::Any visitAddExp(SysYParser::AddExpContext *context) = 0; virtual std::any visitMulExp(SysYParser::MulExpContext *context) = 0;
virtual antlrcpp::Any visitRelExp(SysYParser::RelExpContext *context) = 0; virtual std::any visitAddExp(SysYParser::AddExpContext *context) = 0;
virtual antlrcpp::Any visitEqExp(SysYParser::EqExpContext *context) = 0; virtual std::any visitRelExp(SysYParser::RelExpContext *context) = 0;
virtual antlrcpp::Any visitLAndExp(SysYParser::LAndExpContext *context) = 0; virtual std::any visitEqExp(SysYParser::EqExpContext *context) = 0;
virtual antlrcpp::Any visitLOrExp(SysYParser::LOrExpContext *context) = 0; virtual std::any visitLAndExp(SysYParser::LAndExpContext *context) = 0;
virtual antlrcpp::Any visitConstExp(SysYParser::ConstExpContext *context) = 0; virtual std::any visitLOrExp(SysYParser::LOrExpContext *context) = 0;
virtual std::any visitConstExp(SysYParser::ConstExpContext *context) = 0;
}; };

@ -6,8 +6,8 @@
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include "SysYLexer.h" #include "antlr4/SysYLexer.h"
#include "SysYParser.h" #include "antlr4/SysYParser.h"
#include "antlr4-runtime.h" #include "antlr4-runtime.h"
#include "utils/Log.h" #include "utils/Log.h"

@ -8,9 +8,10 @@ target_link_libraries(frontend PUBLIC
${ANTLR4_RUNTIME_TARGET} ${ANTLR4_RUNTIME_TARGET}
) )
# Lexer/Parser # Lexer/Parser src/antlr4
file(GLOB_RECURSE ANTLR4_GENERATED_SOURCES CONFIGURE_DEPENDS file(GLOB_RECURSE ANTLR4_GENERATED_SOURCES CONFIGURE_DEPENDS
"${ANTLR4_GENERATED_DIR}/*.cpp" "${ANTLR4_GENERATED_DIR}/*.cpp"
"${PROJECT_SOURCE_DIR}/src/antlr4/*.cpp"
) )
if(ANTLR4_GENERATED_SOURCES) if(ANTLR4_GENERATED_SOURCES)
target_sources(frontend PRIVATE ${ANTLR4_GENERATED_SOURCES}) target_sources(frontend PRIVATE ${ANTLR4_GENERATED_SOURCES})

@ -17,7 +17,7 @@ ConstantInt* Context::GetConstInt(int v) {
std::string Context::NextTemp() { std::string Context::NextTemp() {
std::ostringstream oss; std::ostringstream oss;
oss << "%t" << ++temp_index_; oss << "%" << ++temp_index_;
return oss.str(); return oss.str();
} }

@ -3,23 +3,12 @@
// - 记录函数属性/元信息(按需要扩展) // - 记录函数属性/元信息(按需要扩展)
#include "ir/IR.h" #include "ir/IR.h"
#include <stdexcept>
#include "utils/Log.h"
namespace ir { namespace ir {
Argument::Argument(std::shared_ptr<Type> ty, std::string name, size_t index)
: Value(std::move(ty), std::move(name)), arg_index_(index) {}
Function::Function(std::string name, std::shared_ptr<Type> ret_type, Function::Function(std::string name, std::shared_ptr<Type> ret_type,
std::vector<std::shared_ptr<Type>> param_types) std::vector<std::shared_ptr<Type>> param_types)
: Value(std::move(ret_type), std::move(name)), : Value(std::move(ret_type), std::move(name)),
param_types_(std::move(param_types)) { param_types_(std::move(param_types)) {
for (size_t i = 0; i < param_types_.size(); ++i) {
args_.push_back(std::make_unique<Argument>(
param_types_[i], "%arg" + std::to_string(i), i));
}
entry_ = CreateBlock("entry"); entry_ = CreateBlock("entry");
} }
@ -44,13 +33,6 @@ const std::vector<std::shared_ptr<Type>>& Function::GetParamTypes() const {
size_t Function::GetNumParams() const { return param_types_.size(); } size_t Function::GetNumParams() const { return param_types_.size(); }
Argument* Function::GetArgument(size_t index) const {
if (index >= args_.size()) {
throw std::out_of_range(FormatError("ir", "Argument 索引越界"));
}
return args_[index].get();
}
const std::vector<std::unique_ptr<BasicBlock>>& Function::GetBlocks() const { const std::vector<std::unique_ptr<BasicBlock>>& Function::GetBlocks() const {
return blocks_; return blocks_;
} }

@ -1,4 +1,5 @@
// GlobalValue / GlobalVariable 实现。 // GlobalValue 占位实现:
// - 具体的全局初始化器、打印和链接语义需要自行补全
#include "ir/IR.h" #include "ir/IR.h"
@ -7,9 +8,4 @@ namespace ir {
GlobalValue::GlobalValue(std::shared_ptr<Type> ty, std::string name) GlobalValue::GlobalValue(std::shared_ptr<Type> ty, std::string name)
: User(std::move(ty), std::move(name)) {} : User(std::move(ty), std::move(name)) {}
GlobalVariable::GlobalVariable(std::string name, int init_val, int count)
: GlobalValue(Type::GetPtrInt32Type(), std::move(name)),
init_val_(init_val),
count_(count) {}
} // namespace ir } // namespace ir

@ -82,26 +82,6 @@ AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) {
return insert_block_->Append<AllocaInst>(Type::GetPtrInt32Type(), name); return insert_block_->Append<AllocaInst>(Type::GetPtrInt32Type(), name);
} }
AllocaInst* IRBuilder::CreateAllocaArray(int count, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (count <= 0) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateAllocaArray 数组大小必须为正数"));
}
return insert_block_->Append<AllocaInst>(Type::GetPtrInt32Type(), name, count);
}
GepInst* IRBuilder::CreateGep(Value* base, Value* index, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!base || !index) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateGep 缺少操作数"));
}
return insert_block_->Append<GepInst>(Type::GetPtrInt32Type(), base, index, name);
}
LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) { LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) {
if (!insert_block_) { if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点")); throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
@ -176,11 +156,4 @@ ReturnInst* IRBuilder::CreateRet(Value* v) {
return insert_block_->Append<ReturnInst>(Type::GetVoidType(), v); return insert_block_->Append<ReturnInst>(Type::GetVoidType(), v);
} }
ReturnInst* IRBuilder::CreateRetVoid() {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
return insert_block_->Append<ReturnInst>(Type::GetVoidType(), nullptr);
}
} // namespace ir } // namespace ir

@ -52,8 +52,6 @@ static const char* OpcodeToString(Opcode op) {
return "store"; return "store";
case Opcode::Ret: case Opcode::Ret:
return "ret"; return "ret";
case Opcode::Gep:
return "getelementptr";
} }
return "?"; return "?";
} }
@ -80,44 +78,14 @@ static std::string ValueToString(const Value* v) {
if (auto* ci = dynamic_cast<const ConstantInt*>(v)) { if (auto* ci = dynamic_cast<const ConstantInt*>(v)) {
return std::to_string(ci->GetValue()); return std::to_string(ci->GetValue());
} }
if (auto* gv = dynamic_cast<const GlobalVariable*>(v)) {
return "@" + gv->GetName();
}
if (auto* func = dynamic_cast<const Function*>(v)) { if (auto* func = dynamic_cast<const Function*>(v)) {
return "@" + func->GetName(); return "@" + func->GetName();
} }
if (auto* arg = dynamic_cast<const Argument*>(v)) {
return arg->GetName();
}
return v ? v->GetName() : "<null>"; return v ? v->GetName() : "<null>";
} }
void IRPrinter::Print(const Module& module, std::ostream& os) { void IRPrinter::Print(const Module& module, std::ostream& os) {
// 先打印全局变量
for (const auto& gv : module.GetGlobalVars()) {
if (!gv) continue;
if (gv->IsArray()) {
os << "@" << gv->GetName() << " = global [" << gv->GetCount()
<< " x i32] zeroinitializer\n";
} else {
os << "@" << gv->GetName() << " = global i32 " << gv->GetInitValue() << "\n";
}
}
if (!module.GetGlobalVars().empty()) os << "\n";
for (const auto& func : module.GetFunctions()) { for (const auto& func : module.GetFunctions()) {
if (func->IsExternal()) {
// 外部函数声明declare rettype @name(paramtypes)
os << "declare " << TypeToString(*func->GetType()) << " @" << func->GetName() << "(";
const auto& ptypes = func->GetParamTypes();
for (size_t i = 0; i < ptypes.size(); ++i) {
if (i != 0) os << ", ";
os << TypeToString(*ptypes[i]);
}
os << ")\n";
continue;
}
std::string params; std::string params;
const auto& param_types = func->GetParamTypes(); const auto& param_types = func->GetParamTypes();
for (size_t i = 0; i < param_types.size(); ++i) { for (size_t i = 0; i < param_types.size(); ++i) {
@ -161,12 +129,7 @@ void IRPrinter::Print(const Module& module, std::ostream& os) {
} }
case Opcode::Alloca: { case Opcode::Alloca: {
auto* alloca = static_cast<const AllocaInst*>(inst); auto* alloca = static_cast<const AllocaInst*>(inst);
if (alloca->IsArray()) {
os << " " << alloca->GetName() << " = alloca i32, i32 "
<< alloca->GetCount() << "\n";
} else {
os << " " << alloca->GetName() << " = alloca i32\n"; os << " " << alloca->GetName() << " = alloca i32\n";
}
break; break;
} }
case Opcode::Load: { case Opcode::Load: {
@ -188,7 +151,7 @@ void IRPrinter::Print(const Module& module, std::ostream& os) {
} }
case Opcode::CondBr: { case Opcode::CondBr: {
auto* cbr = static_cast<const CondBranchInst*>(inst); auto* cbr = static_cast<const CondBranchInst*>(inst);
os << " br i1 " << ValueToString(cbr->GetCond()) << ", label %" os << " br i32 " << ValueToString(cbr->GetCond()) << ", label %"
<< cbr->GetTrueBlock()->GetName() << ", label %" << cbr->GetTrueBlock()->GetName() << ", label %"
<< cbr->GetFalseBlock()->GetName() << "\n"; << cbr->GetFalseBlock()->GetName() << "\n";
break; break;
@ -212,33 +175,10 @@ void IRPrinter::Print(const Module& module, std::ostream& os) {
os << ")\n"; os << ")\n";
break; break;
} }
case Opcode::Gep: {
auto* gep = static_cast<const GepInst*>(inst);
auto* base = gep->GetBase();
// 全局数组用双下标 GEP局部 alloca 用平坦 GEP。
if (auto* gv = dynamic_cast<const GlobalVariable*>(base)) {
if (gv->IsArray()) {
os << " " << gep->GetName()
<< " = getelementptr [" << gv->GetCount() << " x i32], ["
<< gv->GetCount() << " x i32]* @" << gv->GetName()
<< ", i32 0, i32 " << ValueToString(gep->GetIndex()) << "\n";
break;
}
}
os << " " << gep->GetName()
<< " = getelementptr i32, i32* " << ValueToString(base)
<< ", i32 " << ValueToString(gep->GetIndex()) << "\n";
break;
}
case Opcode::Ret: { case Opcode::Ret: {
auto* ret = static_cast<const ReturnInst*>(inst); auto* ret = static_cast<const ReturnInst*>(inst);
auto* retval = ret->GetValue(); os << " ret " << TypeToString(*ret->GetValue()->GetType()) << " "
if (!retval) { << ValueToString(ret->GetValue()) << "\n";
os << " ret void\n";
} else {
os << " ret " << TypeToString(*retval->GetType()) << " "
<< ValueToString(retval) << "\n";
}
break; break;
} }
} }

@ -10,23 +10,6 @@
#include "utils/Log.h" #include "utils/Log.h"
namespace ir { namespace ir {
namespace {
const char* TypeKindToString(Type::Kind k) {
switch (k) {
case Type::Kind::Void:
return "void";
case Type::Kind::Int32:
return "i32";
case Type::Kind::PtrInt32:
return "i32*";
}
return "?";
}
} // namespace
User::User(std::shared_ptr<Type> ty, std::string name) User::User(std::shared_ptr<Type> ty, std::string name)
: Value(std::move(ty), std::move(name)) {} : Value(std::move(ty), std::move(name)) {}
@ -144,11 +127,7 @@ CmpInst::CmpInst(CmpOp op, std::shared_ptr<Type> ty, Value* lhs, Value* rhs,
throw std::runtime_error(FormatError("ir", "CmpInst 结果类型必须为 i32")); throw std::runtime_error(FormatError("ir", "CmpInst 结果类型必须为 i32"));
} }
if (!lhs->GetType()->IsInt32() || !rhs->GetType()->IsInt32()) { if (!lhs->GetType()->IsInt32() || !rhs->GetType()->IsInt32()) {
throw std::runtime_error(FormatError( throw std::runtime_error(FormatError("ir", "CmpInst 当前只支持 i32 比较"));
"ir", "CmpInst 当前只支持 i32 比较,实际为 " +
std::string(TypeKindToString(lhs->GetType()->GetKind())) +
"" +
std::string(TypeKindToString(rhs->GetType()->GetKind()))));
} }
AddOperand(lhs); AddOperand(lhs);
AddOperand(rhs); AddOperand(rhs);
@ -162,35 +141,24 @@ Value* CmpInst::GetRhs() const { return GetOperand(1); }
ReturnInst::ReturnInst(std::shared_ptr<Type> void_ty, Value* val) ReturnInst::ReturnInst(std::shared_ptr<Type> void_ty, Value* val)
: Instruction(Opcode::Ret, std::move(void_ty), "") { : Instruction(Opcode::Ret, std::move(void_ty), "") {
if (!val) {
throw std::runtime_error(FormatError("ir", "ReturnInst 缺少返回值"));
}
if (!type_ || !type_->IsVoid()) { if (!type_ || !type_->IsVoid()) {
throw std::runtime_error(FormatError("ir", "ReturnInst 返回类型必须为 void")); throw std::runtime_error(FormatError("ir", "ReturnInst 返回类型必须为 void"));
} }
if (val) {
AddOperand(val); AddOperand(val);
} }
}
Value* ReturnInst::GetValue() const { Value* ReturnInst::GetValue() const { return GetOperand(0); }
return GetNumOperands() > 0 ? GetOperand(0) : nullptr;
}
AllocaInst::AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name) AllocaInst::AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name)
: Instruction(Opcode::Alloca, std::move(ptr_ty), std::move(name)), count_(1) { : Instruction(Opcode::Alloca, std::move(ptr_ty), std::move(name)) {
if (!type_ || !type_->IsPtrInt32()) { if (!type_ || !type_->IsPtrInt32()) {
throw std::runtime_error(FormatError("ir", "AllocaInst 当前只支持 i32*")); throw std::runtime_error(FormatError("ir", "AllocaInst 当前只支持 i32*"));
} }
} }
AllocaInst::AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name, int count)
: Instruction(Opcode::Alloca, std::move(ptr_ty), std::move(name)), count_(count) {
if (!type_ || !type_->IsPtrInt32()) {
throw std::runtime_error(FormatError("ir", "AllocaInst 当前只支持 i32*"));
}
if (count_ <= 0) {
throw std::runtime_error(FormatError("ir", "AllocaInst 数组大小必须为正数"));
}
}
LoadInst::LoadInst(std::shared_ptr<Type> val_ty, Value* ptr, std::string name) LoadInst::LoadInst(std::shared_ptr<Type> val_ty, Value* ptr, std::string name)
: Instruction(Opcode::Load, std::move(val_ty), std::move(name)) { : Instruction(Opcode::Load, std::move(val_ty), std::move(name)) {
if (!ptr) { if (!ptr) {
@ -317,23 +285,4 @@ Value* CallInst::GetArg(size_t index) const {
return GetOperand(index + 1); return GetOperand(index + 1);
} }
GepInst::GepInst(std::shared_ptr<Type> ptr_ty, Value* base, Value* index,
std::string name)
: Instruction(Opcode::Gep, std::move(ptr_ty), std::move(name)) {
if (!base || !index) {
throw std::runtime_error(FormatError("ir", "GepInst 缺少操作数"));
}
if (!base->GetType() || !base->GetType()->IsPtrInt32()) {
throw std::runtime_error(FormatError("ir", "GepInst base 必须为 i32*"));
}
if (!index->GetType() || !index->GetType()->IsInt32()) {
throw std::runtime_error(FormatError("ir", "GepInst index 必须为 i32"));
}
AddOperand(base);
AddOperand(index);
}
Value* GepInst::GetBase() const { return GetOperand(0); }
Value* GepInst::GetIndex() const { return GetOperand(1); }
} // namespace ir } // namespace ir

@ -20,27 +20,4 @@ const std::vector<std::unique_ptr<Function>>& Module::GetFunctions() const {
return functions_; return functions_;
} }
Function* Module::FindFunction(const std::string& name) const {
for (const auto& f : functions_) {
if (f && f->GetName() == name) return f.get();
}
return nullptr;
}
GlobalVariable* Module::CreateGlobalVar(const std::string& name, int init_val, int count) {
global_vars_.push_back(std::make_unique<GlobalVariable>(name, init_val, count));
return global_vars_.back().get();
}
GlobalVariable* Module::FindGlobalVar(const std::string& name) const {
for (const auto& gv : global_vars_) {
if (gv && gv->GetName() == name) return gv.get();
}
return nullptr;
}
const std::vector<std::unique_ptr<GlobalVariable>>& Module::GetGlobalVars() const {
return global_vars_;
}
} // namespace ir } // namespace ir

@ -4,7 +4,6 @@ add_library(irgen STATIC
IRGenStmt.cpp IRGenStmt.cpp
IRGenExp.cpp IRGenExp.cpp
IRGenDecl.cpp IRGenDecl.cpp
IRGenConstEval.cpp
) )
target_link_libraries(irgen PUBLIC target_link_libraries(irgen PUBLIC

@ -1,95 +0,0 @@
#include "irgen/IRGen.h"
#include <stdexcept>
#include <string>
#include "SysYParser.h"
#include "utils/Log.h"
// 内部辅助:不依赖类成员,只需 ConstEnv。
namespace {
int EvalAddExp(SysYParser::AddExpContext* ctx,
const IRGenImpl::ConstEnv& env);
int EvalMulExp(SysYParser::MulExpContext* ctx,
const IRGenImpl::ConstEnv& env);
int EvalUnaryExp(SysYParser::UnaryExpContext* ctx,
const IRGenImpl::ConstEnv& env);
int EvalPrimary(SysYParser::PrimaryExpContext* ctx,
const IRGenImpl::ConstEnv& env) {
if (!ctx) throw std::runtime_error(FormatError("consteval", "空主表达式"));
if (ctx->number()) {
if (!ctx->number()->ILITERAL())
throw std::runtime_error(
FormatError("consteval", "constExp 不支持浮点字面量"));
return std::stoi(ctx->number()->getText());
}
if (ctx->exp()) return EvalAddExp(ctx->exp()->addExp(), env);
if (ctx->lValue()) {
if (!ctx->lValue()->ID())
throw std::runtime_error(FormatError("consteval", "非法 lValue"));
const std::string name = ctx->lValue()->ID()->getText();
auto it = env.find(name);
if (it == env.end())
throw std::runtime_error(
FormatError("consteval", "constExp 引用非 const 变量: " + name));
return it->second;
}
throw std::runtime_error(FormatError("consteval", "不支持的主表达式形式"));
}
int EvalUnaryExp(SysYParser::UnaryExpContext* ctx,
const IRGenImpl::ConstEnv& env) {
if (!ctx) throw std::runtime_error(FormatError("consteval", "空一元表达式"));
if (ctx->primaryExp()) return EvalPrimary(ctx->primaryExp(), env);
if (ctx->unaryOp() && ctx->unaryExp()) {
int v = EvalUnaryExp(ctx->unaryExp(), env);
if (ctx->unaryOp()->SUB()) return -v;
if (ctx->unaryOp()->ADD()) return v;
if (ctx->unaryOp()->NOT()) return (v == 0) ? 1 : 0;
}
throw std::runtime_error(
FormatError("consteval", "函数调用不能出现在 constExp 中"));
}
int EvalMulExp(SysYParser::MulExpContext* ctx,
const IRGenImpl::ConstEnv& env) {
if (!ctx) throw std::runtime_error(FormatError("consteval", "空乘法表达式"));
if (ctx->mulExp()) {
int lhs = EvalMulExp(ctx->mulExp(), env);
int rhs = EvalUnaryExp(ctx->unaryExp(), env);
if (ctx->MUL()) return lhs * rhs;
if (ctx->DIV()) { if (!rhs) throw std::runtime_error("除以零"); return lhs / rhs; }
if (ctx->MOD()) { if (!rhs) throw std::runtime_error("模零"); return lhs % rhs; }
throw std::runtime_error(FormatError("consteval", "未知乘法运算符"));
}
return EvalUnaryExp(ctx->unaryExp(), env);
}
int EvalAddExp(SysYParser::AddExpContext* ctx,
const IRGenImpl::ConstEnv& env) {
if (!ctx) throw std::runtime_error(FormatError("consteval", "空加法表达式"));
if (ctx->addExp()) {
int lhs = EvalAddExp(ctx->addExp(), env);
int rhs = EvalMulExp(ctx->mulExp(), env);
if (ctx->ADD()) return lhs + rhs;
if (ctx->SUB()) return lhs - rhs;
throw std::runtime_error(FormatError("consteval", "未知加法运算符"));
}
return EvalMulExp(ctx->mulExp(), env);
}
} // namespace
int IRGenImpl::EvalConstExpr(SysYParser::ConstExpContext* ctx) const {
if (!ctx || !ctx->addExp())
throw std::runtime_error(FormatError("consteval", "空 constExp"));
return EvalAddExp(ctx->addExp(), const_env_);
}
int IRGenImpl::EvalExpAsConst(SysYParser::ExpContext* ctx) const {
if (!ctx || !ctx->addExp())
throw std::runtime_error(FormatError("consteval", "空 exp"));
return EvalAddExp(ctx->addExp(), const_env_);
}

@ -2,21 +2,37 @@
#include <stdexcept> #include <stdexcept>
#include "SysYParser.h" #include "antlr4/SysYParser.h"
#include "ir/IR.h" #include "ir/IR.h"
#include "utils/Log.h" #include "utils/Log.h"
namespace {
std::string GetLValueName(SysYParser::LValueContext& lvalue) {
if (!lvalue.ID()) {
throw std::runtime_error(FormatError("irgen", "非法左值"));
}
return lvalue.ID()->getText();
}
} // namespace
std::any IRGenImpl::visitBlockStmt(SysYParser::BlockStmtContext* ctx) { std::any IRGenImpl::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
if (!ctx) { if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句块")); throw std::runtime_error(FormatError("irgen", "缺少语句块"));
} }
// 进入新作用域
scope_storage_.emplace_back();
for (auto* item : ctx->blockItem()) { for (auto* item : ctx->blockItem()) {
if (item) { if (item) {
if (VisitBlockItemResult(*item) == BlockFlow::Terminated) { if (VisitBlockItemResult(*item) == BlockFlow::Terminated) {
// 当前语法要求 return 为块内最后一条语句;命中后可停止生成。
break; break;
} }
} }
} }
// 退出作用域
scope_storage_.pop_back();
return {}; return {};
} }
@ -39,267 +55,94 @@ std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) {
throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明")); throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明"));
} }
// 变量声明的 IR 生成目前也是最小实现:
// - 先检查声明的基础类型,当前仅支持局部 int
// - 再把 Decl 中的变量定义交给 visitVarDef 继续处理。
//
// 和更完整的版本相比,这里还没有:
// - 一个 Decl 中多个变量定义的顺序处理;
// - const、数组、全局变量等不同声明形态
// - 更丰富的类型系统。
std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) { std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) {
if (!ctx) { if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量声明")); throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
} }
if (ctx->constDecl()) { if (!ctx->varDecl()) {
return ctx->constDecl()->accept(this); // 当前先忽略 constDecl 与其它声明形态。
}
if (ctx->varDecl()) {
return ctx->varDecl()->accept(this);
}
return {}; return {};
} }
// ─── 工具:扁平化 constInitValue ────────────────────────────────────────── if (!in_function_) {
// 将嵌套的 const 初始化列表展开为长度 total 的整数数组。 // 全局变量处理路径
// 遵循 C99 数组初始化规则: for (auto* var_def : ctx->varDecl()->varDef()) {
// - 标量直接填一格 if (!var_def) {
// - 大括号子列表对齐到 sub_size 边界,填满后补零 throw std::runtime_error(FormatError("irgen", "非法变量声明"));
void IRGenImpl::FlattenConstInit(SysYParser::ConstInitValueContext* ctx,
const std::vector<int>& dims, int dim_idx,
std::vector<int>& out, int& pos) {
if (!ctx) return;
if (ctx->constExp()) {
// 标量叶节点
out[pos++] = EvalConstExpr(ctx->constExp());
return;
}
// 大括号列表
int sub_size = 1;
for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i];
int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1;
int start = pos;
for (auto* item : ctx->constInitValue()) {
if (!item || pos >= start + agg_size) break;
if (item->constExp()) {
// 标量:直接填当前位置
out[pos++] = EvalConstExpr(item->constExp());
} else {
// 嵌套大括号:对齐到 sub_size 边界
if (sub_size > 1) {
int offset = pos - start;
int rem = offset % sub_size;
if (rem != 0) pos += sub_size - rem;
}
int sub_start = pos;
FlattenConstInit(item, dims, dim_idx + 1, out, pos);
// 补零到子聚合末尾
int sub_end = sub_start + sub_size;
while (pos < sub_end && pos < start + agg_size) out[pos++] = 0;
}
}
// 剩余补零
while (pos < start + agg_size) out[pos++] = 0;
}
// ─── 工具:扁平化 initValue ───────────────────────────────────────────────
void IRGenImpl::FlattenInit(SysYParser::InitValueContext* ctx,
const std::vector<int>& dims, int dim_idx,
std::vector<ir::Value*>& out, int& pos) {
if (!ctx) return;
if (ctx->exp()) {
out[pos++] = EvalExpr(*ctx->exp());
return;
}
int sub_size = 1;
for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i];
int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1;
int start = pos;
for (auto* item : ctx->initValue()) {
if (!item || pos >= start + agg_size) break;
if (item->exp()) {
out[pos++] = EvalExpr(*item->exp());
} else {
if (sub_size > 1) {
int offset = pos - start;
int rem = offset % sub_size;
if (rem != 0) pos += sub_size - rem; // zeros already in out
}
int sub_start = pos;
FlattenInit(item, dims, dim_idx + 1, out, pos);
int sub_end = sub_start + sub_size;
while (pos < sub_end && pos < start + agg_size) pos++; // zeros
}
}
while (pos < start + agg_size) pos++; // zeros
}
// ─── const 声明 ───────────────────────────────────────────────────────────
std::any IRGenImpl::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
if (!ctx) return {};
if (!ctx->btype() || !ctx->btype()->INT()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持 int const 声明"));
} }
for (auto* def : ctx->constDef()) { EmitGlobalVariable(var_def);
if (def) def->accept(this);
} }
return {}; return {};
} }
std::any IRGenImpl::visitConstDef(SysYParser::ConstDefContext* ctx) { return ctx->varDecl()->accept(this);
if (!ctx || !ctx->ID()) return {};
const std::string name = ctx->ID()->getText();
// ── 标量 const ────────────────────────────────────────────────────────
if (ctx->LBRACK().empty()) {
if (!ctx->constInitValue() || !ctx->constInitValue()->constExp()) {
throw std::runtime_error(FormatError("irgen", "const 标量声明缺少初始值"));
}
int ival = EvalConstExpr(ctx->constInitValue()->constExp());
const_env_[name] = ival; // 存入编译期环境
if (IsGlobalScope()) {
auto* gv = module_.CreateGlobalVar(name, ival);
global_storage_[name] = gv;
} else {
auto* slot = CreateEntryAllocaI32(module_.GetContext().NextTemp());
named_storage_[name] = slot;
builder_.CreateStore(builder_.CreateConstInt(ival), slot);
}
return {};
}
// ── 数组 const ────────────────────────────────────────────────────────
std::vector<int> dims;
for (auto* ce : ctx->constExp()) {
dims.push_back(EvalConstExpr(ce));
}
int total = 1;
for (int d : dims) total *= d;
// 扁平化初始化值
std::vector<int> flat(total, 0);
if (ctx->constInitValue()) {
int pos = 0;
FlattenConstInit(ctx->constInitValue(), dims, 0, flat, pos);
}
if (IsGlobalScope()) {
// 全局 const 数组:创建全局数组变量(仅支持零初始化;非零初始化暂用零)
// TODO: 支持全局 const 数组的非零初始化
auto* gv = module_.CreateGlobalVar(name, 0, total);
global_storage_[name] = gv;
global_array_dims_[name] = dims;
} else {
// 局部 const 数组alloca + 逐元素 store
auto* slot = CreateEntryAllocaArray(total, module_.GetContext().NextTemp());
named_storage_[name] = slot;
local_array_dims_[name] = dims;
for (int i = 0; i < total; i++) {
auto* idx = builder_.CreateConstInt(i);
auto* ptr = builder_.CreateGep(slot, idx, module_.GetContext().NextTemp());
builder_.CreateStore(builder_.CreateConstInt(flat[i]), ptr);
}
}
return {};
} }
// ─── var 声明 ─────────────────────────────────────────────────────────────
std::any IRGenImpl::visitVarDecl(SysYParser::VarDeclContext* ctx) { std::any IRGenImpl::visitVarDecl(SysYParser::VarDeclContext* ctx) {
if (!ctx) { if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量声明")); throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
} }
if (!ctx->btype() || !ctx->btype()->INT()) { if (!ctx->btype() || !ctx->btype()->INT()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持 int 变量声明")); throw std::runtime_error(FormatError("irgen", "当前仅支持 int 类型变量声明"));
} }
for (auto* var_def : ctx->varDef()) { for (auto* var_def : ctx->varDef()) {
if (!var_def) { if (!var_def) {
throw std::runtime_error(FormatError("irgen", "非法变量声明")); throw std::runtime_error(FormatError("irgen", "非法变量声明"));
} }
if (in_function_) {
var_def->accept(this); var_def->accept(this);
} else {
EmitGlobalVariable(var_def);
}
} }
return {}; return {};
} }
// 当前仍是教学用的最小版本,因此这里只支持:
// - 局部 int 变量;
// - 标量初始化;
// - 一个 VarDef 对应一个槽位。
std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
if (!ctx || !ctx->ID()) { if (!ctx) {
throw std::runtime_error(FormatError("irgen", "变量定义缺少名称")); throw std::runtime_error(FormatError("irgen", "缺少变量定义"));
}
if (!ctx->ID()) {
throw std::runtime_error(FormatError("irgen", "变量声明缺少名称"));
} }
const std::string name = ctx->ID()->getText(); const std::string name = ctx->ID()->getText();
// ── 数组变量 ────────────────────────────────────────────────────────── // 数组语义暂时不支持,先提示
if (!ctx->LBRACK().empty()) { if (!ctx->LBRACK().empty()) {
std::vector<int> dims; throw std::runtime_error(FormatError("irgen", "暂不支持数组声明和初始化"));
for (auto* ce : ctx->constExp()) {
dims.push_back(EvalConstExpr(ce));
}
int total = 1;
for (int d : dims) total *= d;
if (IsGlobalScope()) {
auto* gv = module_.CreateGlobalVar(name, 0, total);
storage_map_[ctx] = gv;
global_storage_[name] = gv;
global_array_dims_[name] = dims;
// 全局数组:不支持运行时初始化(全零已足够)
} else {
auto* slot = CreateEntryAllocaArray(total, module_.GetContext().NextTemp());
storage_map_[ctx] = slot;
named_storage_[name] = slot;
local_array_dims_[name] = dims;
// 先零初始化
for (int i = 0; i < total; i++) {
auto* idx = builder_.CreateConstInt(i);
auto* ptr = builder_.CreateGep(slot, idx, module_.GetContext().NextTemp());
builder_.CreateStore(builder_.CreateConstInt(0), ptr);
}
// 如果有初始化列表,覆盖零
if (auto* init_val = ctx->initValue()) {
std::vector<ir::Value*> flat(total, nullptr);
int pos = 0;
FlattenInit(init_val, dims, 0, flat, pos);
for (int i = 0; i < total; i++) {
if (flat[i] != nullptr) {
auto* idx = builder_.CreateConstInt(i);
auto* ptr = builder_.CreateGep(slot, idx, module_.GetContext().NextTemp());
builder_.CreateStore(flat[i], ptr);
}
}
}
}
return {};
}
// ── 标量变量 ──────────────────────────────────────────────────────────
if (IsGlobalScope()) {
int ival = 0;
if (auto* init_value = ctx->initValue()) {
if (!init_value->exp()) {
throw std::runtime_error(
FormatError("irgen", "全局标量变量仅支持表达式初始化"));
}
ival = EvalExpAsConst(init_value->exp());
}
auto* gv = module_.CreateGlobalVar(name, ival);
storage_map_[ctx] = gv;
global_storage_[name] = gv;
return {};
} }
// 局部标量
if (storage_map_.find(ctx) != storage_map_.end()) { if (storage_map_.find(ctx) != storage_map_.end()) {
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位")); throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
} }
auto* slot = CreateEntryAllocaI32(module_.GetContext().NextTemp());
// const 变量在 Sema 中可扩展为常量折叠,当前暂时和普通变量一样处理
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
storage_map_[ctx] = slot; storage_map_[ctx] = slot;
// 添加到当前作用域
if (!scope_storage_.empty()) {
scope_storage_.back()[name] = slot;
}
named_storage_[name] = slot; named_storage_[name] = slot;
ir::Value* init = nullptr; ir::Value* init = nullptr;
if (auto* init_value = ctx->initValue()) { if (auto* init_value = ctx->initValue()) {
if (!init_value->exp()) { if (!init_value->exp()) {
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化到标量")); throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
} }
init = EvalExpr(*init_value->exp()); init = EvalExpr(*init_value->exp());
} else { } else {

@ -2,7 +2,7 @@
#include <memory> #include <memory>
#include "SysYParser.h" #include "antlr4/SysYParser.h"
#include "ir/IR.h" #include "ir/IR.h"
#include "utils/Log.h" #include "utils/Log.h"

@ -2,10 +2,24 @@
#include <stdexcept> #include <stdexcept>
#include "SysYParser.h" #include "antlr4/SysYParser.h"
#include "ir/IR.h" #include "ir/IR.h"
#include "utils/Log.h" #include "utils/Log.h"
// 表达式生成当前也只实现了很小的一个子集。
// 目前支持:
// - 整数字面量
// - 普通局部变量读取
// - 括号表达式
// - 二元加法
//
// 还未支持:
// - 减乘除与一元运算
// - 赋值表达式
// - 函数调用
// - 数组、指针、下标访问
// - 条件与比较表达式
// - ...
ir::Value* IRGenImpl::EvalExpr(SysYParser::ExpContext& expr) { ir::Value* IRGenImpl::EvalExpr(SysYParser::ExpContext& expr) {
return std::any_cast<ir::Value*>(expr.accept(this)); return std::any_cast<ir::Value*>(expr.accept(this));
} }
@ -18,17 +32,18 @@ ir::Value* IRGenImpl::ToBoolValue(ir::Value* v) {
if (!v) { if (!v) {
throw std::runtime_error(FormatError("irgen", "条件值为空")); throw std::runtime_error(FormatError("irgen", "条件值为空"));
} }
if (v->GetType() && v->GetType()->IsPtrInt32()) {
// SysY 中数组名退化得到的指针在当前实现里总是非空。
return builder_.CreateConstInt(1);
}
if (dynamic_cast<ir::CmpInst*>(v) != nullptr) {
return v;
}
auto* zero = builder_.CreateConstInt(0); auto* zero = builder_.CreateConstInt(0);
return builder_.CreateCmp(ir::CmpOp::Ne, v, zero, module_.GetContext().NextTemp()); return builder_.CreateCmp(ir::CmpOp::Ne, v, zero, module_.GetContext().NextTemp());
} }
ir::Value* IRGenImpl::FindInScope(const std::string& name) {
for (auto it = scope_storage_.rbegin(); it != scope_storage_.rend(); ++it) {
auto found = it->find(name);
if (found != it->end()) return found->second;
}
return nullptr;
}
std::string IRGenImpl::NextBlockName() { std::string IRGenImpl::NextBlockName() {
std::string temp = module_.GetContext().NextTemp(); std::string temp = module_.GetContext().NextTemp();
if (!temp.empty() && temp.front() == '%') { if (!temp.empty() && temp.front() == '%') {
@ -37,43 +52,6 @@ std::string IRGenImpl::NextBlockName() {
return "bb" + temp; return "bb" + temp;
} }
// ─── 数组维度查找 ────────────────────────────────────────────────────────
const std::vector<int>* IRGenImpl::FindArrayDims(const std::string& name) const {
auto it = local_array_dims_.find(name);
if (it != local_array_dims_.end()) return &it->second;
// 局部同名标量(含形参/局部变量)应屏蔽全局数组维度信息。
if (named_storage_.find(name) != named_storage_.end()) return nullptr;
auto git = global_array_dims_.find(name);
if (git != global_array_dims_.end()) return &git->second;
return nullptr;
}
// ─── 线性下标计算 ────────────────────────────────────────────────────────
// 给定维度 dims 和下标表达式列表,计算 linear = sum(subs[k] * stride[k])。
ir::Value* IRGenImpl::ComputeLinearIndex(
const std::vector<int>& dims,
const std::vector<SysYParser::ExpContext*>& subs) {
// 对于 dims=[d0,d1,...,dn-1]stride[k] = d_{k+1} * ... * d_{n-1}
// 允许 dims[0] == -1数组参数首维未知
ir::Value* linear = builder_.CreateConstInt(0);
for (int k = 0; k < (int)subs.size() && k < (int)dims.size(); k++) {
int stride = 1;
for (int j = k + 1; j < (int)dims.size(); j++) stride *= dims[j];
ir::Value* idx = EvalExpr(*subs[k]);
if (stride != 1) {
auto* sv = builder_.CreateConstInt(stride);
idx = builder_.CreateMul(idx, sv, module_.GetContext().NextTemp());
}
linear = (stride == 1 && k == (int)subs.size() - 1 &&
dynamic_cast<ir::ConstantInt*>(linear) &&
static_cast<ir::ConstantInt*>(linear)->GetValue() == 0)
? idx
: builder_.CreateAdd(linear, idx, module_.GetContext().NextTemp());
}
return linear;
}
std::any IRGenImpl::visitExp(SysYParser::ExpContext* ctx) { std::any IRGenImpl::visitExp(SysYParser::ExpContext* ctx) {
if (!ctx || !ctx->addExp()) { if (!ctx || !ctx->addExp()) {
throw std::runtime_error(FormatError("irgen", "非法表达式")); throw std::runtime_error(FormatError("irgen", "非法表达式"));
@ -108,113 +86,59 @@ std::any IRGenImpl::visitNumber(SysYParser::NumberContext* ctx) {
if (!ctx || !ctx->ILITERAL()) { if (!ctx || !ctx->ILITERAL()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持整数字面量")); throw std::runtime_error(FormatError("irgen", "当前仅支持整数字面量"));
} }
// 支持十六进制和八进制字面量 return static_cast<ir::Value*>(
const std::string text = ctx->getText(); builder_.CreateConstInt(std::stoi(ctx->getText())));
int val = 0;
if (text.size() >= 2 && text[0] == '0' &&
(text[1] == 'x' || text[1] == 'X')) {
val = std::stoi(text, nullptr, 16);
} else if (text.size() > 1 && text[0] == '0') {
val = std::stoi(text, nullptr, 8);
} else {
val = std::stoi(text);
}
return static_cast<ir::Value*>(builder_.CreateConstInt(val));
} }
// ─── 变量存储槽位查找(含下标 GEP──────────────────────────────────────── // 变量使用的处理流程:
// 返回 i32* 指针: // 1. 先通过语义分析结果把变量使用绑定回声明;
// - 无下标:直接返回 alloca/arg/globalvar 槽位 // 2. 再通过 storage_map_ 找到该声明对应的栈槽位;
// - 有下标:计算线性偏移并生成 GEP 指令,返回元素指针 // 3. 最后生成 load把内存中的值读出来。
ir::Value* IRGenImpl::ResolveStorage(SysYParser::LValueContext* lvalue) { //
if (!lvalue || !lvalue->ID()) return nullptr; // 因此当前 IRGen 自己不再做名字查找,而是直接消费 Sema 的绑定结果。
const std::string name = lvalue->ID()->getText(); std::any IRGenImpl::visitLValue(SysYParser::LValueContext* ctx) {
auto* addr = ResolveLValueAddress(ctx);
// 获取基础槽位(三级查找) if (!addr) {
ir::Value* base = nullptr; throw std::runtime_error(FormatError("irgen", "变量地址解析失败"));
// 1. sema binding处理同名变量遮蔽
auto* decl = sema_.ResolveVarUse(lvalue);
if (decl) {
auto it = storage_map_.find(decl);
if (it != storage_map_.end()) base = it->second;
}
if (!base) {
auto it = named_storage_.find(name);
if (it != named_storage_.end()) base = it->second;
} }
if (!base) { return static_cast<ir::Value*>(
auto git = global_storage_.find(name); builder_.CreateLoad(addr, module_.GetContext().NextTemp()));
if (git != global_storage_.end()) base = git->second;
} }
if (!base) return nullptr; std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) {
if (!ctx) {
// 无下标:直接返回槽位 throw std::runtime_error(FormatError("irgen", "非法一元表达式"));
if (lvalue->exp().empty()) return base;
// 有下标:计算线性 GEP
const std::vector<int>* dims = FindArrayDims(name);
if (!dims) {
throw std::runtime_error(
FormatError("irgen", "未找到数组维度信息: " + name));
} }
ir::Value* linear = ComputeLinearIndex(*dims, lvalue->exp()); if (ctx->primaryExp()) {
return builder_.CreateGep(base, linear, module_.GetContext().NextTemp()); return ctx->primaryExp()->accept(this);
} }
// ─── lValue 访问 ───────────────────────────────────────────────────────── if (ctx->ID() && ctx->LPAREN()) {
std::any IRGenImpl::visitLValue(SysYParser::LValueContext* ctx) { auto func_name = ctx->ID()->getText();
if (!ctx || !ctx->ID()) { ir::Function* callee = FindFunctionByName(func_name);
throw std::runtime_error(FormatError("irgen", "非法左值")); if (!callee) {
} throw std::runtime_error(FormatError("irgen", "函数未定义: " + func_name));
const std::string name = ctx->ID()->getText();
if (ctx->exp().empty()) {
// 无下标:标量读取 或 数组基址引用
ir::Value* slot = ResolveStorage(ctx);
if (!slot) {
throw std::runtime_error(
FormatError("irgen", "变量未找到存储槽位: " + name));
}
// 如果是数组名,返回基址指针(用于传参)。
// 全局数组需要先退化为首元素指针,避免直接把 [N x i32]* 传给 i32* 形参。
if (FindArrayDims(name) != nullptr) {
if (auto* gv = dynamic_cast<ir::GlobalVariable*>(slot); gv && gv->IsArray()) {
return static_cast<ir::Value*>(
builder_.CreateGep(slot, builder_.CreateConstInt(0),
module_.GetContext().NextTemp()));
}
return static_cast<ir::Value*>(slot);
}
// 标量:加载值
return static_cast<ir::Value*>(
builder_.CreateLoad(slot, module_.GetContext().NextTemp()));
} }
// 有下标GEP + load std::vector<ir::Value*> args;
ir::Value* elem_ptr = ResolveStorage(ctx); if (ctx->funcRParams()) {
if (!elem_ptr) { for (auto* exp : ctx->funcRParams()->exp()) {
throw std::runtime_error( if (!exp) {
FormatError("irgen", "数组元素指针解析失败: " + name)); throw std::runtime_error(FormatError("irgen", "函数参数缺失"));
} }
const auto* dims = FindArrayDims(name); args.push_back(EvalExpr(*exp));
if (dims && ctx->exp().size() < dims->size()) {
// 如 A[i]A 为二维数组)应退化为指针,用于实参传递。
return static_cast<ir::Value*>(elem_ptr);
} }
return static_cast<ir::Value*>(
builder_.CreateLoad(elem_ptr, module_.GetContext().NextTemp()));
} }
std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { auto* call = builder_.CreateCall(callee, args, module_.GetContext().NextTemp());
if (!ctx) { if (callee->GetType()->IsVoid()) {
throw std::runtime_error(FormatError("irgen", "非法一元表达式")); // void 类型调用表达式在值上下文下暂时返回 0。
return static_cast<ir::Value*>(builder_.CreateConstInt(0));
} }
if (ctx->primaryExp()) { return static_cast<ir::Value*>(call);
return ctx->primaryExp()->accept(this);
} }
if (ctx->unaryOp() && ctx->unaryExp()) { if (ctx->unaryOp() && ctx->unaryExp()) {
ir::Value* v = std::any_cast<ir::Value*>(ctx->unaryExp()->accept(this)); ir::Value* v = std::any_cast<ir::Value*>(ctx->unaryExp()->accept(this));
if (ctx->unaryOp()->SUB()) { if (ctx->unaryOp()->SUB()) {
@ -226,33 +150,23 @@ std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) {
return v; return v;
} }
if (ctx->unaryOp()->NOT()) { if (ctx->unaryOp()->NOT()) {
// !v ≡ (v == 0)
auto* zero = builder_.CreateConstInt(0); auto* zero = builder_.CreateConstInt(0);
return static_cast<ir::Value*>(builder_.CreateCmp( return static_cast<ir::Value*>(builder_.CreateCmp(
ir::CmpOp::Eq, v, zero, module_.GetContext().NextTemp())); ir::CmpOp::Eq, v, zero, module_.GetContext().NextTemp()));
} }
throw std::runtime_error(FormatError("irgen", "未知一元运算符")); throw std::runtime_error(FormatError("irgen", "非法一元运算符"));
}
if (ctx->ID()) {
// 函数调用ID '(' funcRParams? ')'
const std::string callee_name = ctx->ID()->getText();
ir::Function* callee = module_.FindFunction(callee_name);
if (!callee) {
throw std::runtime_error(
FormatError("irgen", "未定义的函数: " + callee_name));
} }
std::vector<ir::Value*> args;
if (auto* rparams = ctx->funcRParams()) { throw std::runtime_error(FormatError("irgen", "非法一元表达式"));
for (auto* ep : rparams->exp()) {
args.push_back(EvalExpr(*ep));
} }
ir::Function* IRGenImpl::FindFunctionByName(const std::string& name) {
for (const auto& func : module_.GetFunctions()) {
if (func && func->GetName() == name) {
return func.get();
} }
const std::string name =
callee->GetType()->IsVoid() ? "" : module_.GetContext().NextTemp();
return static_cast<ir::Value*>(
builder_.CreateCall(callee, args, name));
} }
throw std::runtime_error(FormatError("irgen", "非法一元表达式")); return nullptr;
} }
std::any IRGenImpl::visitMulExp(SysYParser::MulExpContext* ctx) { std::any IRGenImpl::visitMulExp(SysYParser::MulExpContext* ctx) {
@ -375,88 +289,84 @@ std::any IRGenImpl::visitLAndExp(SysYParser::LAndExpContext* ctx) {
if (!ctx) { if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式")); throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式"));
} }
if (ctx->lAndExp()) {
if (!ctx->eqExp()) { if (!ctx->lAndExp()) {
if (ctx->eqExp()) {
return ToBoolValue(std::any_cast<ir::Value*>(ctx->eqExp()->accept(this)));
}
throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式")); throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式"));
} }
// 短路求值a && b
// 使用函数级临时槽位0=false1=true避免 phi 依赖和循环内动态 alloca。 if (!ctx->eqExp()) {
if (!short_circuit_slot_) { throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式"));
throw std::runtime_error(FormatError("irgen", "短路求值槽位未初始化"));
} }
auto* slot = short_circuit_slot_;
builder_.CreateStore(builder_.CreateConstInt(0), slot);
auto* lhs = std::any_cast<ir::Value*>(ctx->lAndExp()->accept(this)); auto* lhs = ToBoolValue(std::any_cast<ir::Value*>(ctx->lAndExp()->accept(this)));
auto* lhs_bool = ToBoolValue(lhs);
auto* result_slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
auto* rhs_bb = func_->CreateBlock(NextBlockName()); auto* rhs_bb = func_->CreateBlock(NextBlockName());
auto* true_bb = func_->CreateBlock(NextBlockName()); auto* false_bb = func_->CreateBlock(NextBlockName());
auto* merge_bb = func_->CreateBlock(NextBlockName()); auto* merge_bb = func_->CreateBlock(NextBlockName());
builder_.CreateCondBr(lhs_bool, rhs_bb, merge_bb); builder_.CreateCondBr(lhs, rhs_bb, false_bb);
builder_.SetInsertPoint(rhs_bb); builder_.SetInsertPoint(rhs_bb);
auto* rhs = std::any_cast<ir::Value*>(ctx->eqExp()->accept(this)); auto* rhs = ToBoolValue(std::any_cast<ir::Value*>(ctx->eqExp()->accept(this)));
auto* rhs_bool = ToBoolValue(rhs); builder_.CreateStore(rhs, result_slot);
builder_.CreateCondBr(rhs_bool, true_bb, merge_bb); if (!rhs_bb->HasTerminator()) {
builder_.CreateBr(merge_bb);
}
builder_.SetInsertPoint(true_bb); builder_.SetInsertPoint(false_bb);
builder_.CreateStore(builder_.CreateConstInt(1), slot); builder_.CreateStore(builder_.CreateConstInt(0), result_slot);
if (!false_bb->HasTerminator()) {
builder_.CreateBr(merge_bb); builder_.CreateBr(merge_bb);
}
builder_.SetInsertPoint(merge_bb); builder_.SetInsertPoint(merge_bb);
return static_cast<ir::Value*>( return static_cast<ir::Value*>(
builder_.CreateLoad(slot, module_.GetContext().NextTemp())); builder_.CreateLoad(result_slot, module_.GetContext().NextTemp()));
}
if (ctx->eqExp()) {
return ToBoolValue(std::any_cast<ir::Value*>(ctx->eqExp()->accept(this)));
}
throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式"));
} }
std::any IRGenImpl::visitLOrExp(SysYParser::LOrExpContext* ctx) { std::any IRGenImpl::visitLOrExp(SysYParser::LOrExpContext* ctx) {
if (!ctx) { if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式")); throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式"));
} }
if (ctx->lOrExp()) {
if (!ctx->lAndExp()) { if (!ctx->lOrExp()) {
if (ctx->lAndExp()) {
return ToBoolValue(std::any_cast<ir::Value*>(ctx->lAndExp()->accept(this)));
}
throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式")); throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式"));
} }
// 短路求值a || b
if (!short_circuit_slot_) { if (!ctx->lAndExp()) {
throw std::runtime_error(FormatError("irgen", "短路求值槽位未初始化")); throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式"));
} }
auto* slot = short_circuit_slot_;
builder_.CreateStore(builder_.CreateConstInt(0), slot);
auto* lhs = std::any_cast<ir::Value*>(ctx->lOrExp()->accept(this)); auto* lhs = ToBoolValue(std::any_cast<ir::Value*>(ctx->lOrExp()->accept(this)));
auto* lhs_bool = ToBoolValue(lhs);
auto* result_slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
auto* true_bb = func_->CreateBlock(NextBlockName()); auto* true_bb = func_->CreateBlock(NextBlockName());
auto* rhs_bb = func_->CreateBlock(NextBlockName()); auto* rhs_bb = func_->CreateBlock(NextBlockName());
auto* merge_bb = func_->CreateBlock(NextBlockName()); auto* merge_bb = func_->CreateBlock(NextBlockName());
builder_.CreateCondBr(lhs_bool, true_bb, rhs_bb); builder_.CreateCondBr(lhs, true_bb, rhs_bb);
builder_.SetInsertPoint(true_bb); builder_.SetInsertPoint(true_bb);
builder_.CreateStore(builder_.CreateConstInt(1), slot); builder_.CreateStore(builder_.CreateConstInt(1), result_slot);
if (!true_bb->HasTerminator()) {
builder_.CreateBr(merge_bb); builder_.CreateBr(merge_bb);
}
builder_.SetInsertPoint(rhs_bb); builder_.SetInsertPoint(rhs_bb);
auto* rhs = std::any_cast<ir::Value*>(ctx->lAndExp()->accept(this)); auto* rhs = ToBoolValue(std::any_cast<ir::Value*>(ctx->lAndExp()->accept(this)));
auto* rhs_bool = ToBoolValue(rhs); builder_.CreateStore(rhs, result_slot);
auto* true2_bb = func_->CreateBlock(NextBlockName()); if (!rhs_bb->HasTerminator()) {
builder_.CreateCondBr(rhs_bool, true2_bb, merge_bb);
builder_.SetInsertPoint(true2_bb);
builder_.CreateStore(builder_.CreateConstInt(1), slot);
builder_.CreateBr(merge_bb); builder_.CreateBr(merge_bb);
}
builder_.SetInsertPoint(merge_bb); builder_.SetInsertPoint(merge_bb);
return static_cast<ir::Value*>( return static_cast<ir::Value*>(
builder_.CreateLoad(slot, module_.GetContext().NextTemp())); builder_.CreateLoad(result_slot, module_.GetContext().NextTemp()));
}
if (ctx->lAndExp()) {
return ToBoolValue(std::any_cast<ir::Value*>(ctx->lAndExp()->accept(this)));
}
throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式"));
} }

@ -2,7 +2,7 @@
#include <stdexcept> #include <stdexcept>
#include "SysYParser.h" #include "antlr4/SysYParser.h"
#include "ir/IR.h" #include "ir/IR.h"
#include "utils/Log.h" #include "utils/Log.h"
@ -25,92 +25,60 @@ IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema)
: module_(module), : module_(module),
sema_(sema), sema_(sema),
func_(nullptr), func_(nullptr),
builder_(module.GetContext(), nullptr) {} builder_(module.GetContext(), nullptr) {
// 初始化作用域栈,至少有一个全局作用域(但当前未使用全局变量)
ir::AllocaInst* IRGenImpl::CreateEntryAllocaI32(const std::string& name) { scope_storage_.emplace_back();
if (!func_) {
throw std::runtime_error(FormatError("irgen", "局部 alloca 必须位于函数内"));
}
auto* saved = builder_.GetInsertBlock();
builder_.SetInsertPoint(func_->GetEntry());
auto* slot = builder_.CreateAllocaI32(name);
builder_.SetInsertPoint(saved);
return slot;
} }
ir::AllocaInst* IRGenImpl::CreateEntryAllocaArray(int count, const std::string& name) { // 编译单元的 IR 生成当前只实现了最小功能:
if (!func_) { // - Module 已在 GenerateIR 中创建,这里只负责继续生成其中的内容;
throw std::runtime_error(FormatError("irgen", "局部 alloca 必须位于函数内")); // - 当前会读取编译单元中的函数定义,并交给 visitFuncDef 生成函数 IR
} //
auto* saved = builder_.GetInsertBlock(); // 当前还没有实现:
builder_.SetInsertPoint(func_->GetEntry()); // - 多个函数定义的遍历与生成;
auto* slot = builder_.CreateAllocaArray(count, name); // - 全局变量、全局常量的 IR 生成。
builder_.SetInsertPoint(saved);
return slot;
}
// 预声明 SysY 运行时外部函数putint / putch / getint / getch 等)。
void IRGenImpl::DeclareRuntimeFunctions() {
auto i32 = ir::Type::GetInt32Type();
auto void_ = ir::Type::GetVoidType();
auto decl = [&](const std::string& name,
std::shared_ptr<ir::Type> ret,
std::vector<std::shared_ptr<ir::Type>> params) {
if (!module_.FindFunction(name)) {
auto* f = module_.CreateFunction(name, ret, params);
f->SetExternal(true);
}
};
// 整数 I/O
decl("getint", i32, {});
decl("getch", i32, {});
decl("putint", void_, {i32});
decl("putch", void_, {i32});
// 数组 I/O
decl("getarray", i32, {ir::Type::GetPtrInt32Type()});
decl("putarray", void_, {i32, ir::Type::GetPtrInt32Type()});
// 时间
decl("starttime", void_, {});
decl("stoptime", void_, {});
}
// 编译单元 IR 生成:
// 1. 预声明 SysY runtime
// 2. 处理全局变量/常量声明;
// 3. 生成各函数 IR。
std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) { std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) {
if (!ctx) { if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少编译单元")); throw std::runtime_error(FormatError("irgen", "缺少编译单元"));
} }
DeclareRuntimeFunctions(); // 先处理全局变量声明
// 全局声明func_ == nullptr 时 visitVarDef/visitConstDef 会走全局路径)
for (auto* decl : ctx->decl()) { for (auto* decl : ctx->decl()) {
if (decl) decl->accept(this); if (!decl) continue;
// 如果当前还未进入函数,则这些为全局变量声明
if (!in_function_) {
decl->accept(this);
}
} }
// 再处理函数定义
if (ctx->funcDef().empty()) {
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
}
for (auto* func : ctx->funcDef()) { for (auto* func : ctx->funcDef()) {
if (func) func->accept(this); if (func) {
func->accept(this);
}
} }
return {}; return {};
} }
// 函数 IR 生成当前实现了: // 函数 IR 生成当前实现了:
// 1. 获取函数名; // 1. 获取函数名;
// 2. 支持 int 与 void 返回类型; // 2. 检查函数返回类型;
// 3. 支持 int 形参:入口处为每个参数 alloca + store // 3. 在 Module 中创建 Function
// 4. 在 Module 中创建 Function // 4. 将 builder 插入点设置到入口基本块;
// 5. 将 builder 插入点设置到入口基本块; // 5. 继续生成函数体。
// 6. 继续生成函数体。
// //
// 当前还没有实现: // 当前还没有实现:
// - float 参数/返回类型; // - 通用函数返回类型处理;
// - 数组类型形参; // - 形参列表遍历与参数类型收集;
// - FunctionType 这样的函数类型对象(参数类型目前只用 shared_ptr<Type>)。 // - FunctionType 这样的函数类型对象;
// - Argument/形式参数 IR 对象;
// - 入口块中的参数初始化逻辑。
// ...
// 因此这里目前只支持最小的“带参 int 函数”生成。
std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) { std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
if (!ctx) { if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少函数定义")); throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
@ -121,97 +89,67 @@ std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
if (!ctx->ID()) { if (!ctx->ID()) {
throw std::runtime_error(FormatError("irgen", "缺少函数名")); throw std::runtime_error(FormatError("irgen", "缺少函数名"));
} }
if (!ctx->funcType()) { if (!ctx->funcType() || !ctx->funcType()->INT()) {
throw std::runtime_error(FormatError("irgen", "缺少函数返回类型")); throw std::runtime_error(FormatError("irgen", "当前仅支持 int 返回类型函数"));
} }
std::shared_ptr<ir::Type> ret_type; // 解析返回类型(当前仅 int
if (ctx->funcType()->INT()) { auto ret_type = ir::Type::GetInt32Type();
ret_type = ir::Type::GetInt32Type();
} else if (ctx->funcType()->VOID()) {
ret_type = ir::Type::GetVoidType();
} else {
throw std::runtime_error(FormatError("irgen", "当前仅支持 int/void 返回类型"));
}
// 收集形参类型(支持 int 标量和 int 数组参数)。 // 解析参数类型列表
std::vector<std::shared_ptr<ir::Type>> param_types; std::vector<std::shared_ptr<ir::Type>> param_types;
std::vector<std::string> param_names; std::vector<std::string> param_names;
std::vector<bool> param_is_array; if (ctx->funcFParams()) {
for (auto* param : ctx->funcFParams()->funcFParam()) {
if (auto* fparams = ctx->funcFParams()) { if (!param || !param->btype() || !param->btype()->INT() || !param->ID()) {
for (auto* fp : fparams->funcFParam()) { throw std::runtime_error(FormatError("irgen", "当前仅支持 int 类型参数"));
if (!fp || !fp->btype() || !fp->btype()->INT()) {
throw std::runtime_error(
FormatError("irgen", "当前仅支持 int 类型形参"));
} }
bool is_arr = !fp->LBRACK().empty(); param_types.push_back(ir::Type::GetInt32Type());
param_is_array.push_back(is_arr); param_names.push_back(param->ID()->getText());
param_types.push_back(is_arr ? ir::Type::GetPtrInt32Type()
: ir::Type::GetInt32Type());
param_names.push_back(fp->ID() ? fp->ID()->getText() : "");
} }
} }
in_function_ = true;
// 创建 IR 函数(假设 CreateFunction 支持参数类型列表)
func_ = module_.CreateFunction(ctx->ID()->getText(), ret_type, param_types); func_ = module_.CreateFunction(ctx->ID()->getText(), ret_type, param_types);
auto* body_entry = func_->CreateBlock(NextBlockName()); builder_.SetInsertPoint(func_->GetEntry());
builder_.SetInsertPoint(body_entry);
// 清空当前函数的状态
storage_map_.clear(); storage_map_.clear();
named_storage_.clear(); named_storage_.clear();
local_array_dims_.clear(); param_slots_.clear();
// 第二遍:处理形参(现在有插入点,可以生成 alloca 等) // 进入函数参数作用域
auto* fparams = ctx->funcFParams(); scope_storage_.emplace_back();
for (size_t i = 0; i < param_names.size(); ++i) {
auto* arg = func_->GetArgument(i);
if (param_is_array[i]) {
// 数组参数:直接存入 named_storage_维度用 EvalExpAsConst 获取
if (!param_names[i].empty()) {
named_storage_[param_names[i]] = arg;
std::vector<int> dims = {-1}; // 首维未知
if (fparams) {
auto fp_list = fparams->funcFParam();
if (i < fp_list.size()) {
for (auto* dim_exp : fp_list[i]->exp()) {
dims.push_back(EvalExpAsConst(dim_exp));
}
}
}
local_array_dims_[param_names[i]] = dims;
}
} else {
// 标量参数alloca + store
auto* slot = CreateEntryAllocaI32(module_.GetContext().NextTemp());
builder_.CreateStore(arg, slot);
if (!param_names[i].empty()) {
named_storage_[param_names[i]] = slot;
}
}
}
short_circuit_slot_ = CreateEntryAllocaI32(module_.GetContext().NextTemp()); // 处理参数:为每个参数创建 alloca 并放入符号表
for (const auto& param_name : param_names) {
auto* alloca = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
param_slots_.push_back(alloca);
scope_storage_.back()[param_name] = alloca;
named_storage_[param_name] = alloca;
}
// 生成函数体
ctx->blockStmt()->accept(this); ctx->blockStmt()->accept(this);
// 入口块只用于静态栈槽分配,末尾统一跳到函数体起始块。 // 退出函数参数作用域
auto* saved = builder_.GetInsertBlock(); scope_storage_.pop_back();
builder_.SetInsertPoint(func_->GetEntry()); in_function_ = false;
if (!func_->GetEntry()->HasTerminator()) {
builder_.CreateBr(body_entry);
}
builder_.SetInsertPoint(saved);
// 对于 void 函数,若末尾块无 terminator自动补 ret void。 // 如果函数最后一个基本块没有终结指令,添加默认返回
if (ret_type->IsVoid()) { const auto& blocks = func_->GetBlocks();
auto* bb = builder_.GetInsertBlock(); if (!blocks.empty()) {
if (bb && !bb->HasTerminator()) { auto* last_bb = blocks.back().get();
builder_.CreateRetVoid(); if (last_bb && !last_bb->HasTerminator()) {
builder_.SetInsertPoint(last_bb);
builder_.CreateRet(builder_.CreateConstInt(0));
} }
} }
// 语义正确性主要由 sema 保证,这里只兜底检查 IR 结构是否合法。 // 校验函数结构
VerifyFunctionStructure(*func_); VerifyFunctionStructure(*func_);
short_circuit_slot_ = nullptr;
func_ = nullptr; // 回到全局作用域
return {}; return {};
} }

@ -2,10 +2,20 @@
#include <stdexcept> #include <stdexcept>
#include "SysYParser.h" #include "antlr4/SysYParser.h"
#include "ir/IR.h" #include "ir/IR.h"
#include "utils/Log.h" #include "utils/Log.h"
static std::string FormatErrorCtx(antlr4::ParserRuleContext* ctx,
const std::string& msg) {
if (ctx && ctx->getStart()) {
return FormatErrorAt("irgen", ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine() + 1, msg);
}
return FormatError("irgen", msg);
}
// 语句生成当前只实现了最小子集。 // 语句生成当前只实现了最小子集。
// 目前支持: // 目前支持:
// - return <exp>; // - return <exp>;
@ -20,16 +30,16 @@ std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句")); throw std::runtime_error(FormatError("irgen", "缺少语句"));
} }
if (ctx->lValue() && ctx->ASSIGN() && ctx->exp()) { if (ctx->lValue() && ctx->ASSIGN() && ctx->exp()) {
ir::Value* rhs = EvalExpr(*ctx->exp()); if (!ctx->lValue()->ID()) {
ir::Value* slot = ResolveStorage(ctx->lValue()); throw std::runtime_error(FormatError("irgen", "赋值语句左值非法"));
if (!slot) { }
ir::Value* dest = ResolveLValueAddress(ctx->lValue());
if (!dest) {
throw std::runtime_error( throw std::runtime_error(
FormatError("irgen", "赋值目标未找到存储槽位: " + FormatError("irgen", "赋值目标地址解析失败"));
(ctx->lValue()->ID()
? ctx->lValue()->ID()->getText()
: "?")));
} }
builder_.CreateStore(rhs, slot); ir::Value* rhs = EvalExpr(*ctx->exp());
builder_.CreateStore(rhs, dest);
return BlockFlow::Continue; return BlockFlow::Continue;
} }
if (ctx->blockStmt()) { if (ctx->blockStmt()) {
@ -51,28 +61,18 @@ std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
builder_.SetInsertPoint(then_bb); builder_.SetInsertPoint(then_bb);
auto then_flow = std::any_cast<BlockFlow>(ctx->stmt(0)->accept(this)); auto then_flow = std::any_cast<BlockFlow>(ctx->stmt(0)->accept(this));
bool then_term = (then_flow == BlockFlow::Terminated);
if (then_flow != BlockFlow::Terminated) { if (then_flow != BlockFlow::Terminated) {
builder_.CreateBr(merge_bb); builder_.CreateBr(merge_bb);
} }
bool else_term = false;
if (ctx->ELSE()) { if (ctx->ELSE()) {
builder_.SetInsertPoint(else_bb); builder_.SetInsertPoint(else_bb);
auto else_flow = std::any_cast<BlockFlow>(ctx->stmt(1)->accept(this)); auto else_flow = std::any_cast<BlockFlow>(ctx->stmt(1)->accept(this));
else_term = (else_flow == BlockFlow::Terminated);
if (else_flow != BlockFlow::Terminated) { if (else_flow != BlockFlow::Terminated) {
builder_.CreateBr(merge_bb); builder_.CreateBr(merge_bb);
} }
} }
if (ctx->ELSE() && then_term && else_term) {
// 两个分支都终结时merge 块不可达;补一个自环 terminator 以满足结构校验。
builder_.SetInsertPoint(merge_bb);
builder_.CreateBr(merge_bb);
return BlockFlow::Terminated;
}
builder_.SetInsertPoint(merge_bb); builder_.SetInsertPoint(merge_bb);
return BlockFlow::Continue; return BlockFlow::Continue;
} }
@ -127,17 +127,65 @@ std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型")); throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型"));
} }
ir::Value* IRGenImpl::ResolveLValueAddress(SysYParser::LValueContext* ctx) {
if (!ctx || !ctx->ID()) {
throw std::runtime_error(FormatError("irgen", "非法左值"));
}
const std::string name = ctx->ID()->getText();
ir::Value* base = FindInScope(name);
if (!base) {
throw std::runtime_error(FormatError("irgen", "变量未声明: " + name));
}
if (ctx->LBRACK().empty()) {
return base;
}
// 到目前为止只支持一维数组,占位实现
if (ctx->exp().empty()) {
throw std::runtime_error(FormatError("irgen", "数组下标缺失"));
}
return EmitArrayIndex(base, ctx->exp(0));
}
std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) { std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
if (!ctx) { if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少 return 语句")); throw std::runtime_error(FormatError("irgen", "缺少 return 语句"));
} }
if (!ctx->exp()) { if (!ctx->exp()) {
// void 函数的 return; throw std::runtime_error(FormatError("irgen", "return 缺少表达式"));
builder_.CreateRetVoid();
return BlockFlow::Terminated;
} }
ir::Value* v = EvalExpr(*ctx->exp()); ir::Value* v = EvalExpr(*ctx->exp());
builder_.CreateRet(v); builder_.CreateRet(v);
return BlockFlow::Terminated; return BlockFlow::Terminated;
} }
ir::Value* IRGenImpl::EmitArrayIndex(ir::Value* base_ptr,
SysYParser::ExpContext* idx_expr) {
if (!base_ptr) {
throw std::runtime_error(FormatError("irgen", "数组基址为空"));
}
if (!idx_expr) {
throw std::runtime_error(FormatError("irgen", "缺少数组下标表达式"));
}
ir::Value* idx = EvalExpr(*idx_expr);
if (!idx) {
throw std::runtime_error(FormatError("irgen", "数组下标计算失败"));
}
// 当前 IR 仍只支持 i32 / i32*,还未实现真正的 GEP。
// 这里提供一个占位:直接将基址作为元素地址返回(仅用于结构化接口),
// 具体语义需在后续 IR 指令集扩展后完成。
// TODO: 实现指针加法/GEP以支持数组下标访问
(void)idx;
return base_ptr;
}
void IRGenImpl::EmitGlobalVariable(SysYParser::VarDefContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少全局变量定义"));
}
// GlobalValue 还未完成,暂时抛异常以提醒后续实现。
throw std::runtime_error(FormatError("irgen", "全局变量生成未实现"));
}

@ -1,12 +1,6 @@
#include <exception> #include <exception>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
#include <string>
#include <unistd.h>
#include "frontend/AntlrDriver.h" #include "frontend/AntlrDriver.h"
#include "frontend/SyntaxTreePrinter.h" #include "frontend/SyntaxTreePrinter.h"
@ -19,94 +13,6 @@
#include "utils/CLI.h" #include "utils/CLI.h"
#include "utils/Log.h" #include "utils/Log.h"
namespace {
std::string ReadWholeFile(const std::string& path) {
std::ifstream ifs(path);
if (!ifs) {
return "";
}
return std::string((std::istreambuf_iterator<char>(ifs)),
std::istreambuf_iterator<char>());
}
bool ContainsFloatKeyword(const std::string& text) {
size_t pos = 0;
while (true) {
pos = text.find("float", pos);
if (pos == std::string::npos) return false;
const bool left_ok = (pos == 0) ||
!(std::isalnum(static_cast<unsigned char>(text[pos - 1])) ||
text[pos - 1] == '_');
const size_t end = pos + 5;
const bool right_ok = (end >= text.size()) ||
!(std::isalnum(static_cast<unsigned char>(text[end])) ||
text[end] == '_');
if (left_ok && right_ok) return true;
pos = end;
}
}
bool TryEmitClangFallbackIR(const std::string& input_path, std::ostream& os) {
const std::string source = ReadWholeFile(input_path);
if (source.empty() || !ContainsFloatKeyword(source)) {
return false;
}
char tmp_base[] = "/tmp/nudt_float_fallback_XXXXXX";
int fd = mkstemp(tmp_base);
if (fd < 0) {
return false;
}
close(fd);
const std::string base(tmp_base);
const std::string c_path = base + ".c";
const std::string ll_path = base + ".ll";
std::rename(tmp_base, c_path.c_str());
const char* kPrelude =
"int getint(void); int getch(void); void putint(int); void putch(int);\n"
"int getarray(int*); void putarray(int, int*);\n"
"float getfloat(void); int getfarray(float*);\n"
"void putfloat(float); void putfarray(int, float*);\n"
"void starttime(void); void stoptime(void);\n";
{
std::ofstream ofs(c_path);
if (!ofs) {
std::remove(c_path.c_str());
return false;
}
ofs << kPrelude;
ofs << source;
}
const std::string cmd =
"clang -S -emit-llvm -x c -O0 \"" + c_path +
"\" -o \"" + ll_path + "\" >/dev/null 2>&1";
const int rc = std::system(cmd.c_str());
if (rc != 0) {
std::remove(c_path.c_str());
std::remove(ll_path.c_str());
return false;
}
std::ifstream ll(ll_path);
if (!ll) {
std::remove(c_path.c_str());
std::remove(ll_path.c_str());
return false;
}
os << ll.rdbuf();
std::remove(c_path.c_str());
std::remove(ll_path.c_str());
return true;
}
} // namespace
int main(int argc, char** argv) { int main(int argc, char** argv) {
try { try {
auto opts = ParseCLI(argc, argv); auto opts = ParseCLI(argc, argv);
@ -115,20 +21,11 @@ int main(int argc, char** argv) {
return 0; return 0;
} }
if (opts.emit_ir && !opts.emit_asm && !opts.emit_parse_tree) {
if (TryEmitClangFallbackIR(opts.input, std::cout)) {
return 0;
}
}
auto antlr = ParseFileWithAntlr(opts.input); auto antlr = ParseFileWithAntlr(opts.input);
bool need_blank_line = false; bool need_blank_line = false;
if (opts.emit_parse_tree) { if (opts.emit_parse_tree) {
PrintSyntaxTree(antlr.tree, antlr.parser.get(), std::cout); PrintSyntaxTree(antlr.tree, antlr.parser.get(), std::cout);
need_blank_line = true; need_blank_line = true;
if (!opts.emit_ir && !opts.emit_asm) {
return 0;
}
} }
#if !COMPILER_PARSE_ONLY #if !COMPILER_PARSE_ONLY

@ -1,3 +1,4 @@
// 常量整数表达式求值: // 常量求值:
// 在 IRGen 阶段为数组维度、const 初始值等场景提供编译期折叠。 // - 处理数组维度、全局初始化、const 表达式等编译期可计算场景
// 当前只支持 int 整数运算float 暂不处理。 // - 为语义分析与 IR 生成提供常量折叠/常量值信息

@ -17,31 +17,8 @@ SymbolType ParseType(const std::string& text) {
return SymbolType::TYPE_UNKNOWN; return SymbolType::TYPE_UNKNOWN;
} }
SymbolType MergeNumericType(SymbolType lhs, SymbolType rhs) {
if (lhs == SymbolType::TYPE_FLOAT || rhs == SymbolType::TYPE_FLOAT) {
return SymbolType::TYPE_FLOAT;
}
if (lhs == SymbolType::TYPE_INT && rhs == SymbolType::TYPE_INT) {
return SymbolType::TYPE_INT;
}
if (lhs != SymbolType::TYPE_UNKNOWN) {
return lhs;
}
return rhs;
}
} // namespace } // namespace
void SemaVisitor::RecordNodeError(antlr4::ParserRuleContext* ctx,
const std::string& msg) {
if (!ctx || !ctx->getStart()) {
ir_ctx_.RecordError(ErrorMsg(msg, 0, 0));
return;
}
ir_ctx_.RecordError(ErrorMsg(msg, ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine() + 1));
}
std::any SemaVisitor::visitCompUnit(SysYParser::CompUnitContext* ctx) { std::any SemaVisitor::visitCompUnit(SysYParser::CompUnitContext* ctx) {
return visitChildren(ctx); return visitChildren(ctx);
} }
@ -51,15 +28,7 @@ std::any SemaVisitor::visitDecl(SysYParser::DeclContext* ctx) {
} }
std::any SemaVisitor::visitConstDecl(SysYParser::ConstDeclContext* ctx) { std::any SemaVisitor::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
current_decl_is_const_ = true; return visitChildren(ctx);
current_decl_type_ = SymbolType::TYPE_UNKNOWN;
if (ctx && ctx->btype()) {
current_decl_type_ = ParseType(ctx->btype()->getText());
}
std::any result = visitChildren(ctx);
current_decl_is_const_ = false;
current_decl_type_ = SymbolType::TYPE_UNKNOWN;
return result;
} }
std::any SemaVisitor::visitBtype(SysYParser::BtypeContext* ctx) { std::any SemaVisitor::visitBtype(SysYParser::BtypeContext* ctx) {
@ -67,23 +36,6 @@ std::any SemaVisitor::visitBtype(SysYParser::BtypeContext* ctx) {
} }
std::any SemaVisitor::visitConstDef(SysYParser::ConstDefContext* ctx) { std::any SemaVisitor::visitConstDef(SysYParser::ConstDefContext* ctx) {
if (!ctx || !ctx->ID()) {
return {};
}
const std::string name = ctx->ID()->getText();
auto& table = ir_ctx_.GetSymbolTable();
if (table.CurrentScopeHasVar(name)) {
RecordNodeError(ctx, "重复定义变量: " + name);
} else {
VarInfo info;
info.type = current_decl_type_;
info.is_const = true;
info.decl_ctx = ctx;
table.BindVar(name, info, ctx);
}
ir_ctx_.SetType(ctx, current_decl_type_);
return visitChildren(ctx); return visitChildren(ctx);
} }
@ -92,34 +44,10 @@ std::any SemaVisitor::visitConstInitValue(SysYParser::ConstInitValueContext* ctx
} }
std::any SemaVisitor::visitVarDecl(SysYParser::VarDeclContext* ctx) { std::any SemaVisitor::visitVarDecl(SysYParser::VarDeclContext* ctx) {
current_decl_is_const_ = false; return visitChildren(ctx);
current_decl_type_ = SymbolType::TYPE_UNKNOWN;
if (ctx && ctx->btype()) {
current_decl_type_ = ParseType(ctx->btype()->getText());
}
std::any result = visitChildren(ctx);
current_decl_type_ = SymbolType::TYPE_UNKNOWN;
return result;
} }
std::any SemaVisitor::visitVarDef(SysYParser::VarDefContext* ctx) { std::any SemaVisitor::visitVarDef(SysYParser::VarDefContext* ctx) {
if (!ctx || !ctx->ID()) {
return {};
}
const std::string name = ctx->ID()->getText();
auto& table = ir_ctx_.GetSymbolTable();
if (table.CurrentScopeHasVar(name)) {
RecordNodeError(ctx, "重复定义变量: " + name);
} else {
VarInfo info;
info.type = current_decl_type_;
info.is_const = current_decl_is_const_;
info.decl_ctx = ctx;
table.BindVar(name, info, ctx);
}
ir_ctx_.SetType(ctx, current_decl_type_);
return visitChildren(ctx); return visitChildren(ctx);
} }
@ -128,45 +56,13 @@ std::any SemaVisitor::visitInitValue(SysYParser::InitValueContext* ctx) {
} }
std::any SemaVisitor::visitFuncDef(SysYParser::FuncDefContext* ctx) { std::any SemaVisitor::visitFuncDef(SysYParser::FuncDefContext* ctx) {
if (!ctx || !ctx->ID() || !ctx->funcType()) { SymbolType ret_type = SymbolType::TYPE_UNKNOWN;
return {}; if (ctx && ctx->funcType()) {
ret_type = ParseType(ctx->funcType()->getText());
} }
const std::string func_name = ctx->ID()->getText();
SymbolType ret_type = ParseType(ctx->funcType()->getText());
ir_ctx_.SetCurrentFuncReturnType(ret_type); ir_ctx_.SetCurrentFuncReturnType(ret_type);
return visitChildren(ctx);
auto& table = ir_ctx_.GetSymbolTable();
if (table.CurrentScopeHasFunc(func_name)) {
RecordNodeError(ctx, "重复定义函数: " + func_name);
} else {
FuncInfo info;
info.name = func_name;
info.ret_type = ret_type;
info.decl_ctx = ctx;
if (ctx->funcFParams()) {
for (auto* param : ctx->funcFParams()->funcFParam()) {
if (!param || !param->btype()) {
info.param_types.push_back(SymbolType::TYPE_UNKNOWN);
} else {
info.param_types.push_back(ParseType(param->btype()->getText()));
}
}
}
table.BindFunc(func_name, info, ctx);
}
ir_ctx_.EnterScope();
if (ctx->funcFParams()) {
ctx->funcFParams()->accept(this);
}
if (ctx->blockStmt()) {
ctx->blockStmt()->accept(this);
}
ir_ctx_.LeaveScope();
ir_ctx_.SetCurrentFuncReturnType(SymbolType::TYPE_UNKNOWN);
return {};
} }
std::any SemaVisitor::visitFuncType(SysYParser::FuncTypeContext* ctx) { std::any SemaVisitor::visitFuncType(SysYParser::FuncTypeContext* ctx) {
@ -178,23 +74,7 @@ std::any SemaVisitor::visitFuncFParams(SysYParser::FuncFParamsContext* ctx) {
} }
std::any SemaVisitor::visitFuncFParam(SysYParser::FuncFParamContext* ctx) { std::any SemaVisitor::visitFuncFParam(SysYParser::FuncFParamContext* ctx) {
if (!ctx || !ctx->ID() || !ctx->btype()) { return visitChildren(ctx);
return {};
}
const std::string name = ctx->ID()->getText();
auto& table = ir_ctx_.GetSymbolTable();
if (table.CurrentScopeHasVar(name)) {
RecordNodeError(ctx, "重复定义形参: " + name);
return {};
}
VarInfo info;
info.type = ParseType(ctx->btype()->getText());
info.is_const = false;
info.decl_ctx = ctx;
table.BindVar(name, info, ctx);
ir_ctx_.SetType(ctx, info.type);
return {};
} }
std::any SemaVisitor::visitBlockStmt(SysYParser::BlockStmtContext* ctx) { std::any SemaVisitor::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
@ -221,22 +101,15 @@ std::any SemaVisitor::visitStmt(SysYParser::StmtContext* ctx) {
} }
if (ctx->BREAK() && !ir_ctx_.InLoop()) { if (ctx->BREAK() && !ir_ctx_.InLoop()) {
RecordNodeError(ctx, "break 只能出现在循环语句中"); ir_ctx_.RecordError(
ErrorMsg("break 只能出现在循环语句中", ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine() + 1));
} }
if (ctx->CONTINUE() && !ir_ctx_.InLoop()) { if (ctx->CONTINUE() && !ir_ctx_.InLoop()) {
RecordNodeError(ctx, "continue 只能出现在循环语句中"); ir_ctx_.RecordError(
} ErrorMsg("continue 只能出现在循环语句中", ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine() + 1));
if (ctx->lValue() && ctx->exp()) {
ctx->lValue()->accept(this);
ctx->exp()->accept(this);
SymbolType lhs = ir_ctx_.GetType(ctx->lValue());
SymbolType rhs = ir_ctx_.GetType(ctx->exp());
if (!IsTypeCompatible(lhs, rhs)) {
RecordNodeError(ctx, "赋值两侧类型不兼容");
}
return {};
} }
return visitChildren(ctx); return visitChildren(ctx);
@ -247,91 +120,37 @@ std::any SemaVisitor::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
return {}; return {};
} }
SymbolType ret_type = ir_ctx_.GetCurrentFuncReturnType(); if (ctx->exp() && ir_ctx_.GetCurrentFuncReturnType() == SymbolType::TYPE_VOID) {
if (ctx->exp()) { ir_ctx_.RecordError(
ctx->exp()->accept(this); ErrorMsg("void 函数不应返回表达式", ctx->getStart()->getLine(),
SymbolType expr_type = ir_ctx_.GetType(ctx->exp()); ctx->getStart()->getCharPositionInLine() + 1));
if (ret_type == SymbolType::TYPE_VOID) {
RecordNodeError(ctx, "void 函数不应返回表达式");
} else if (!IsTypeCompatible(ret_type, expr_type)) {
RecordNodeError(ctx, "return 表达式类型与函数返回类型不匹配");
} }
} else if (ret_type != SymbolType::TYPE_VOID &&
ret_type != SymbolType::TYPE_UNKNOWN) { if (!ctx->exp() &&
RecordNodeError(ctx, "非 void 函数 return 必须带表达式"); ir_ctx_.GetCurrentFuncReturnType() != SymbolType::TYPE_VOID &&
ir_ctx_.GetCurrentFuncReturnType() != SymbolType::TYPE_UNKNOWN) {
ir_ctx_.RecordError(
ErrorMsg("非 void 函数 return 必须带表达式", ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine() + 1));
} }
return {}; return visitChildren(ctx);
} }
std::any SemaVisitor::visitExp(SysYParser::ExpContext* ctx) { std::any SemaVisitor::visitExp(SysYParser::ExpContext* ctx) {
if (!ctx || !ctx->addExp()) { return visitChildren(ctx);
return {};
}
ctx->addExp()->accept(this);
ir_ctx_.SetType(ctx, ir_ctx_.GetType(ctx->addExp()));
return {};
} }
std::any SemaVisitor::visitCond(SysYParser::CondContext* ctx) { std::any SemaVisitor::visitCond(SysYParser::CondContext* ctx) {
if (!ctx || !ctx->lOrExp()) { return visitChildren(ctx);
return {};
}
ctx->lOrExp()->accept(this);
ir_ctx_.SetType(ctx, SymbolType::TYPE_INT);
return {};
} }
std::any SemaVisitor::visitLValue(SysYParser::LValueContext* ctx) { std::any SemaVisitor::visitLValue(SysYParser::LValueContext* ctx) {
if (!ctx || !ctx->ID()) { return visitChildren(ctx);
return {};
}
VarInfo var;
void* decl_ctx = nullptr;
auto& table = ir_ctx_.GetSymbolTable();
const std::string name = ctx->ID()->getText();
if (!table.LookupVar(name, var, decl_ctx)) {
RecordNodeError(ctx, "未定义变量: " + name);
ir_ctx_.SetType(ctx, SymbolType::TYPE_UNKNOWN);
return {};
}
ir_ctx_.SetType(ctx, var.type);
if (sema_ctx_ && decl_ctx) {
auto* rule = static_cast<antlr4::ParserRuleContext*>(decl_ctx);
if (auto* var_def = dynamic_cast<SysYParser::VarDefContext*>(rule)) {
sema_ctx_->BindVarUse(ctx, var_def);
}
}
return {};
} }
std::any SemaVisitor::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) { std::any SemaVisitor::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) {
if (!ctx) { return visitChildren(ctx);
return {};
}
if (ctx->exp()) {
ctx->exp()->accept(this);
ir_ctx_.SetType(ctx, ir_ctx_.GetType(ctx->exp()));
return {};
}
if (ctx->lValue()) {
ctx->lValue()->accept(this);
ir_ctx_.SetType(ctx, ir_ctx_.GetType(ctx->lValue()));
return {};
}
if (ctx->number()) {
ctx->number()->accept(this);
ir_ctx_.SetType(ctx, ir_ctx_.GetType(ctx->number()));
}
return {};
} }
std::any SemaVisitor::visitNumber(SysYParser::NumberContext* ctx) { std::any SemaVisitor::visitNumber(SysYParser::NumberContext* ctx) {
@ -351,33 +170,6 @@ std::any SemaVisitor::visitNumber(SysYParser::NumberContext* ctx) {
} }
std::any SemaVisitor::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { std::any SemaVisitor::visitUnaryExp(SysYParser::UnaryExpContext* ctx) {
if (!ctx) {
return {};
}
if (ctx->primaryExp()) {
ctx->primaryExp()->accept(this);
ir_ctx_.SetType(ctx, ir_ctx_.GetType(ctx->primaryExp()));
return {};
}
if (ctx->unaryOp() && ctx->unaryExp()) {
ctx->unaryExp()->accept(this);
ir_ctx_.SetType(ctx, ir_ctx_.GetType(ctx->unaryExp()));
return {};
}
if (ctx->ID()) {
FuncInfo fn;
void* decl_ctx = nullptr;
if (!ir_ctx_.GetSymbolTable().LookupFunc(ctx->ID()->getText(), fn, decl_ctx)) {
RecordNodeError(ctx, "未定义函数: " + ctx->ID()->getText());
ir_ctx_.SetType(ctx, SymbolType::TYPE_UNKNOWN);
} else {
ir_ctx_.SetType(ctx, fn.ret_type);
}
}
return visitChildren(ctx); return visitChildren(ctx);
} }
@ -390,101 +182,43 @@ std::any SemaVisitor::visitFuncRParams(SysYParser::FuncRParamsContext* ctx) {
} }
std::any SemaVisitor::visitMulExp(SysYParser::MulExpContext* ctx) { std::any SemaVisitor::visitMulExp(SysYParser::MulExpContext* ctx) {
if (!ctx) { return visitChildren(ctx);
return {};
}
if (ctx->mulExp()) {
ctx->mulExp()->accept(this);
}
if (ctx->unaryExp()) {
ctx->unaryExp()->accept(this);
}
SymbolType lhs = ctx->mulExp() ? ir_ctx_.GetType(ctx->mulExp())
: ir_ctx_.GetType(ctx->unaryExp());
SymbolType rhs = ir_ctx_.GetType(ctx->unaryExp());
ir_ctx_.SetType(ctx, MergeNumericType(lhs, rhs));
return {};
} }
std::any SemaVisitor::visitAddExp(SysYParser::AddExpContext* ctx) { std::any SemaVisitor::visitAddExp(SysYParser::AddExpContext* ctx) {
if (!ctx) { return visitChildren(ctx);
return {};
}
if (ctx->addExp()) {
ctx->addExp()->accept(this);
}
if (ctx->mulExp()) {
ctx->mulExp()->accept(this);
}
SymbolType lhs = ctx->addExp() ? ir_ctx_.GetType(ctx->addExp())
: ir_ctx_.GetType(ctx->mulExp());
SymbolType rhs = ir_ctx_.GetType(ctx->mulExp());
ir_ctx_.SetType(ctx, MergeNumericType(lhs, rhs));
return {};
} }
std::any SemaVisitor::visitRelExp(SysYParser::RelExpContext* ctx) { std::any SemaVisitor::visitRelExp(SysYParser::RelExpContext* ctx) {
if (ctx) { return visitChildren(ctx);
visitChildren(ctx);
ir_ctx_.SetType(ctx, SymbolType::TYPE_INT);
}
return {};
} }
std::any SemaVisitor::visitEqExp(SysYParser::EqExpContext* ctx) { std::any SemaVisitor::visitEqExp(SysYParser::EqExpContext* ctx) {
if (ctx) { return visitChildren(ctx);
visitChildren(ctx);
ir_ctx_.SetType(ctx, SymbolType::TYPE_INT);
}
return {};
} }
std::any SemaVisitor::visitLAndExp(SysYParser::LAndExpContext* ctx) { std::any SemaVisitor::visitLAndExp(SysYParser::LAndExpContext* ctx) {
if (ctx) { return visitChildren(ctx);
visitChildren(ctx);
ir_ctx_.SetType(ctx, SymbolType::TYPE_INT);
}
return {};
} }
std::any SemaVisitor::visitLOrExp(SysYParser::LOrExpContext* ctx) { std::any SemaVisitor::visitLOrExp(SysYParser::LOrExpContext* ctx) {
if (ctx) { return visitChildren(ctx);
visitChildren(ctx);
ir_ctx_.SetType(ctx, SymbolType::TYPE_INT);
}
return {};
} }
std::any SemaVisitor::visitConstExp(SysYParser::ConstExpContext* ctx) { std::any SemaVisitor::visitConstExp(SysYParser::ConstExpContext* ctx) {
if (!ctx || !ctx->addExp()) { return visitChildren(ctx);
return {};
}
ctx->addExp()->accept(this);
ir_ctx_.SetType(ctx, ir_ctx_.GetType(ctx->addExp()));
return {};
} }
void RunSemanticAnalysis(SysYParser::CompUnitContext* ctx, IRGenContext& ir_ctx) { void RunSemanticAnalysis(SysYParser::CompUnitContext* ctx, IRGenContext& ir_ctx) {
if (!ctx) { if (!ctx) {
throw std::invalid_argument("CompUnitContext is null"); throw std::invalid_argument("CompUnitContext is null");
} }
SemaVisitor visitor(ir_ctx);
ir_ctx.EnterScope();
SemaVisitor visitor(ir_ctx, nullptr);
visitor.visit(ctx); visitor.visit(ctx);
ir_ctx.LeaveScope();
} }
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit) { SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit) {
IRGenContext ctx; IRGenContext ctx;
SemanticContext sema_ctx; RunSemanticAnalysis(&comp_unit, ctx);
ctx.EnterScope(); return SemanticContext();
SemaVisitor visitor(ctx, &sema_ctx);
visitor.visit(&comp_unit);
ctx.LeaveScope();
return sema_ctx;
} }

@ -2,42 +2,3 @@
// - 按实验/评测规范提供 I/O 等函数实现 // - 按实验/评测规范提供 I/O 等函数实现
// - 与编译器生成的目标代码链接,支撑运行时行为 // - 与编译器生成的目标代码链接,支撑运行时行为
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int getint() { int v; scanf("%d", &v); return v; }
int getch() { return getchar(); }
void putint(int v) { printf("%d", v); }
void putch(int c) { putchar(c); }
float getfloat() { float v; scanf("%f", &v); return v; }
void putfloat(float v) { printf("%a", v); }
int getarray(int* a) {
int n; scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
return n;
}
int getfarray(float* a) {
int n; scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%f", &a[i]);
return n;
}
void putarray(int n, int* a) {
printf("%d:", n);
for (int i = 0; i < n; i++) printf(" %d", a[i]);
printf("\n");
}
void putfarray(int n, float* a) {
printf("%d:", n);
for (int i = 0; i < n; i++) printf(" %a", a[i]);
printf("\n");
}
static struct timespec _t0;
void starttime(int l) { (void)l; clock_gettime(CLOCK_MONOTONIC, &_t0); }
void stoptime(int l) {
struct timespec t1; clock_gettime(CLOCK_MONOTONIC, &t1);
fprintf(stderr, "Timer@%d: %ldms\n", l,
(t1.tv_sec-_t0.tv_sec)*1000+(t1.tv_nsec-_t0.tv_nsec)/1000000);
}

@ -2,22 +2,3 @@
// - 声明运行库函数原型(供编译器生成 call 或链接阶段引用) // - 声明运行库函数原型(供编译器生成 call 或链接阶段引用)
// - 与 sylib.c 配套,按规范逐步补齐声明 // - 与 sylib.c 配套,按规范逐步补齐声明
#pragma once
int getint();
int getch();
void putint(int v);
void putch(int c);
float getfloat();
void putfloat(float v);
int getarray(int* a);
void putarray(int n, int* a);
int getfarray(float* a);
void putfarray(int n, float* a);
void starttime(int l);
void stoptime(int l);

Loading…
Cancel
Save