feat: 添加“while 语句”支持,并对解析器进行重构以处理控制流相关内容
- 引入了 WhileStmt 结构来表示 while 循环语句。 - 在解析器中实现了对 while 语句的解析逻辑。 - 在分析器中为 while 语句添加了语义分析。 - 重构了现有的解析器方法,以利用 StateProtector 进行状态管理。 - 更新了对各种表达式和语句的错误处理。 - 移除了未使用的终止符管理方法,并简化了表达式解析。 - 将 FigLSPServer.cpp 重命名为 LSPServer.cpp,并调整了构建配置。 - 增强了重复声明和类型错误的错误报告。 - 在多个文件中改进了代码格式和一致性。
This commit is contained in:
Binary file not shown.
@@ -17,3 +17,4 @@
|
|||||||
#include <Ast/Stmt/ExprStmt.hpp>
|
#include <Ast/Stmt/ExprStmt.hpp>
|
||||||
#include <Ast/Stmt/IfStmt.hpp>
|
#include <Ast/Stmt/IfStmt.hpp>
|
||||||
#include <Ast/Stmt/VarDecl.hpp>
|
#include <Ast/Stmt/VarDecl.hpp>
|
||||||
|
#include <Ast/Stmt/WhileStmt.hpp>
|
||||||
@@ -36,7 +36,8 @@ namespace Fig
|
|||||||
ExprStmt, // 表达式语句,如 println(1)
|
ExprStmt, // 表达式语句,如 println(1)
|
||||||
VarDecl, // 变量声明
|
VarDecl, // 变量声明
|
||||||
IfStmt, // If语句
|
IfStmt, // If语句
|
||||||
ElseIfStmt, // ElseIf语句,不准悬空
|
ElseIfStmt, // ElseIf语句,不准悬空,平铺式else if
|
||||||
|
WhileStmt, // while语句
|
||||||
};
|
};
|
||||||
struct AstNode
|
struct AstNode
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,9 +16,17 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
// Analyzer槽位,存储具体深度
|
// Analyzer槽位
|
||||||
int resolvedDepth = -1; // 代表未解析
|
|
||||||
bool isGlobal = false; // 是否全局/对外公开 (isPublic)
|
// 寻址空间
|
||||||
|
bool isGlobal = false; // 是否全局, 全局变量存哈希/堆
|
||||||
|
|
||||||
|
// 仅 isGlobal = false 有效
|
||||||
|
int resolvedDepth = -1; // 用于获取闭包上值, -1 代表未解析
|
||||||
|
|
||||||
|
// 栈内槽位
|
||||||
|
int localId = -1; // 局部变量id, -1 未解析
|
||||||
|
|
||||||
|
|
||||||
IdentiExpr()
|
IdentiExpr()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ namespace Fig
|
|||||||
bool isInfer; // 是否用了 := 类型推断
|
bool isInfer; // 是否用了 := 类型推断
|
||||||
Expr *initExpr;
|
Expr *initExpr;
|
||||||
|
|
||||||
|
int localId = -1;
|
||||||
|
|
||||||
VarDecl()
|
VarDecl()
|
||||||
{
|
{
|
||||||
type = AstType::VarDecl;
|
type = AstType::VarDecl;
|
||||||
|
|||||||
37
src/Ast/Stmt/WhileStmt.hpp
Normal file
37
src/Ast/Stmt/WhileStmt.hpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*!
|
||||||
|
@file src/Ast/Stmt/WhileStmt.hpp
|
||||||
|
@brief WhileStmt定义
|
||||||
|
@author PuqiAR (im@puqiar.top)
|
||||||
|
@date 2026-02-24
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Ast/Base.hpp>
|
||||||
|
|
||||||
|
namespace Fig
|
||||||
|
{
|
||||||
|
struct WhileStmt final : public Stmt
|
||||||
|
{
|
||||||
|
Expr *cond;
|
||||||
|
BlockStmt *body;
|
||||||
|
|
||||||
|
WhileStmt()
|
||||||
|
{
|
||||||
|
type = AstType::WhileStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
WhileStmt(Expr *_cond, BlockStmt *_body, SourceLocation _location) :
|
||||||
|
cond(_cond),
|
||||||
|
body(_body)
|
||||||
|
{
|
||||||
|
type = AstType::WhileStmt;
|
||||||
|
location = std::move(_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual String toString() const override
|
||||||
|
{
|
||||||
|
return std::format("<WhileStmt ({}) {{{}}}>", cond->toString(), body->toString());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Fig
|
||||||
@@ -16,7 +16,7 @@ namespace Fig
|
|||||||
|
|
||||||
for (Stmt *stmt : program->nodes)
|
for (Stmt *stmt : program->nodes)
|
||||||
{
|
{
|
||||||
const auto &result = CompileStmt(static_cast<Stmt *>(stmt));
|
auto result = compileStmt(static_cast<Stmt *>(stmt));
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
|
|||||||
@@ -29,12 +29,14 @@ namespace Fig
|
|||||||
|
|
||||||
struct LocalVar
|
struct LocalVar
|
||||||
{
|
{
|
||||||
bool isPublic; // 是否向上级/同级其他域公开
|
int localId; // AST 传来的纯数字 ID
|
||||||
String name;
|
std::uint8_t reg; // 分配到的物理寄存器 ID
|
||||||
std::uint8_t reg; // 寄存器(相对 frame base 的寄存器 id)
|
int depth; // 物理作用域深度(用于 EndScope 释放寄存器)
|
||||||
int depth; // 作用域深度
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr int MAX_LOCALS = 250;
|
||||||
|
static constexpr int MAX_CONSTANTS = UINT16_MAX;
|
||||||
|
|
||||||
// 任何跨函数、跨模块的编译,都压入弹出这个 State
|
// 任何跨函数、跨模块的编译,都压入弹出这个 State
|
||||||
struct FuncState
|
struct FuncState
|
||||||
{
|
{
|
||||||
@@ -46,9 +48,12 @@ namespace Fig
|
|||||||
int scopeDepth = 0;
|
int scopeDepth = 0;
|
||||||
DynArray<LocalVar> locals;
|
DynArray<LocalVar> locals;
|
||||||
|
|
||||||
|
std::uint8_t fastRegMap[UINT8_MAX + 1]; // 256, 索引 = localId, 值 = 寄存器 id
|
||||||
|
|
||||||
FuncState(String _name, FuncState *enc = nullptr) : name(std::move(_name)), enclosing(enc)
|
FuncState(String _name, FuncState *enc = nullptr) : name(std::move(_name)), enclosing(enc)
|
||||||
{
|
{
|
||||||
proto = new Proto();
|
proto = new Proto();
|
||||||
|
std::fill_n(fastRegMap, 256, UINT8_MAX); // 255代表未分配
|
||||||
}
|
}
|
||||||
// 注意:这里不 delete proto,因为 proto 是要作为编译产物吐出去的
|
// 注意:这里不 delete proto,因为 proto 是要作为编译产物吐出去的
|
||||||
};
|
};
|
||||||
@@ -100,7 +105,7 @@ namespace Fig
|
|||||||
|
|
||||||
std::uint8_t AllocReg()
|
std::uint8_t AllocReg()
|
||||||
{
|
{
|
||||||
if (current->freeReg >= 250)
|
if (current->freeReg >= 255)
|
||||||
{
|
{
|
||||||
assert(false && "Register overflow!");
|
assert(false && "Register overflow!");
|
||||||
}
|
}
|
||||||
@@ -137,6 +142,13 @@ namespace Fig
|
|||||||
std::uint16_t AddConstant(Value v)
|
std::uint16_t AddConstant(Value v)
|
||||||
{
|
{
|
||||||
// TODO: 查重
|
// TODO: 查重
|
||||||
|
auto it =
|
||||||
|
std::find(current->proto->constants.begin(), current->proto->constants.end(), v);
|
||||||
|
if (it != current->proto->constants.end())
|
||||||
|
{
|
||||||
|
return std::distance(current->proto->constants.begin(), it);
|
||||||
|
}
|
||||||
|
|
||||||
current->proto->constants.push_back(v);
|
current->proto->constants.push_back(v);
|
||||||
return static_cast<std::uint16_t>(current->proto->constants.size() - 1);
|
return static_cast<std::uint16_t>(current->proto->constants.size() - 1);
|
||||||
}
|
}
|
||||||
@@ -156,73 +168,18 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasLocalInCurrentScope(const String &name)
|
std::uint8_t DeclareLocal(int localId)
|
||||||
{
|
|
||||||
// 逆向查重
|
|
||||||
for (auto it = current->locals.rbegin(); it != current->locals.rend(); ++it)
|
|
||||||
{
|
|
||||||
if (it->depth < current->scopeDepth)
|
|
||||||
break; // 已经超出了当前深度,提前阻断
|
|
||||||
if (it->name == name)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasLocal(const String &name)
|
|
||||||
{
|
|
||||||
for (auto it = current->locals.rbegin(); it != current->locals.rend(); ++it)
|
|
||||||
{
|
|
||||||
if (it->name == name)
|
|
||||||
{
|
|
||||||
if (it->depth == current->scopeDepth)
|
|
||||||
{
|
|
||||||
return true; // 同级不管 public直接捕获
|
|
||||||
}
|
|
||||||
else if (it->isPublic)
|
|
||||||
{
|
|
||||||
return true; // 不同级变量 public才能被捕捉
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint8_t ResolveLocal(const String &name)
|
|
||||||
{
|
|
||||||
// 变量遮蔽: 永远先使用同级已有的变量, 所以逆向遍历
|
|
||||||
for (auto it = current->locals.rbegin(); it != current->locals.rend(); ++it)
|
|
||||||
{
|
|
||||||
if (it->name == name)
|
|
||||||
{
|
|
||||||
if (it->depth < current->scopeDepth && !it->isPublic)
|
|
||||||
{
|
|
||||||
assert(
|
|
||||||
false
|
|
||||||
&& "ResolveLocal: Attempt to access a private variable from an outer scope!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return it->reg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果在本 Frame 没找到,那就是外层函数的变量 (闭包 Upvalue) 或者全局变量 (Global)。
|
|
||||||
assert(
|
|
||||||
false
|
|
||||||
&& "ResolveLocal: Variable not found in current frame (Upvalue/Global not implemented yet)!");
|
|
||||||
return UINT8_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint8_t DeclareLocal(bool isPublic, const String &name)
|
|
||||||
{
|
{
|
||||||
std::uint8_t reg = AllocReg();
|
std::uint8_t reg = AllocReg();
|
||||||
current->locals.push_back(LocalVar{isPublic, name, reg, current->scopeDepth});
|
current->locals.push_back(LocalVar{localId, reg, current->scopeDepth});
|
||||||
|
current->fastRegMap[localId] = reg;
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::uint8_t DeclareLocal(bool isPublic, const String &name, std::uint8_t reg)
|
std::uint8_t DeclareLocal(int localId, std::uint8_t reg) // 表示复用哪个寄存器
|
||||||
{
|
{
|
||||||
current->locals.push_back(LocalVar{isPublic, name, reg, current->scopeDepth});
|
current->locals.push_back(LocalVar{localId, reg, current->scopeDepth});
|
||||||
|
current->fastRegMap[localId] = reg;
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,23 +218,25 @@ namespace Fig
|
|||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<std::uint8_t, Error> CompileIdentiExpr(IdentiExpr *);
|
Result<std::uint8_t, Error> compileIdentiExpr(IdentiExpr *);
|
||||||
Result<std::uint8_t, Error> CompileLiteral(LiteralExpr *);
|
Result<std::uint8_t, Error> compileLiteral(LiteralExpr *);
|
||||||
|
|
||||||
Result<std::uint8_t, Error> CompileAssignment(
|
Result<std::uint8_t, Error> compileAssignment(
|
||||||
InfixExpr *); // 编译赋值,由 CompileInfixExpr调用
|
InfixExpr *); // 编译赋值,由 CompileInfixExpr调用
|
||||||
Result<std::uint8_t, Error> CompileInfixExpr(InfixExpr *);
|
Result<std::uint8_t, Error> compileInfixExpr(InfixExpr *);
|
||||||
|
|
||||||
Result<std::uint8_t, Error> CompileLeftValue(
|
Result<std::uint8_t, Error> compileLeftValue(
|
||||||
Expr *); // 左值对象,可以是变量、结构体字段或模块对象
|
Expr *); // 左值对象,可以是变量、结构体字段或模块对象
|
||||||
|
|
||||||
Result<std::uint8_t, Error> CompileExpr(Expr *);
|
Result<std::uint8_t, Error> compileExpr(Expr *);
|
||||||
|
|
||||||
/* Statements */
|
/* Statements */
|
||||||
Result<void, Error> CompileVarDecl(VarDecl *);
|
Result<void, Error> compileVarDecl(VarDecl *);
|
||||||
Result<void, Error> CompileBlockStmt(BlockStmt *);
|
Result<void, Error> compileBlockStmt(BlockStmt *);
|
||||||
Result<void, Error> CompileIfStmt(IfStmt *);
|
Result<void, Error> compileIfStmt(IfStmt *);
|
||||||
Result<void, Error> CompileStmt(Stmt *);
|
Result<void, Error> compileWhileStmt(WhileStmt *);
|
||||||
|
|
||||||
|
Result<void, Error> compileStmt(Stmt *);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void DisassembleInstruction(Instruction inst, std::size_t index)
|
inline void DisassembleInstruction(Instruction inst, std::size_t index)
|
||||||
|
|||||||
@@ -9,18 +9,18 @@
|
|||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
Result<std::uint8_t, Error> Compiler::CompileIdentiExpr(IdentiExpr *ie)
|
Result<std::uint8_t, Error> Compiler::compileIdentiExpr(IdentiExpr *ie)
|
||||||
{
|
{
|
||||||
// if (!HasLocal(ie->name))
|
// TODO: 处理全局变量和闭包 Upvalue
|
||||||
// {
|
std::uint8_t targetReg = current->fastRegMap[ie->localId];
|
||||||
// return std::unexpected(Error(ErrorType::UseUndeclaredIdentifier,
|
|
||||||
// std::format("`{}` has not been defined", ie->name),
|
if (targetReg == UINT8_MAX)
|
||||||
// "none",
|
{
|
||||||
// makeSourceLocation(ie)));
|
assert(false && "Compiler Bug: Encountered unmapped localId in fastRegMap!");
|
||||||
// }
|
|
||||||
return ResolveLocal(ie->name);
|
|
||||||
}
|
}
|
||||||
Result<std::uint8_t, Error> Compiler::CompileLiteral(
|
return targetReg;
|
||||||
|
}
|
||||||
|
Result<std::uint8_t, Error> Compiler::compileLiteral(
|
||||||
LiteralExpr *lit) // 编译字面量, 负责转换 token -> Value
|
LiteralExpr *lit) // 编译字面量, 负责转换 token -> Value
|
||||||
{
|
{
|
||||||
const Token &token = lit->token;
|
const Token &token = lit->token;
|
||||||
@@ -47,8 +47,8 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else if (token.type == TokenType::LiteralNumber)
|
else if (token.type == TokenType::LiteralNumber)
|
||||||
{
|
{
|
||||||
// TODO: 更换为无异常手写数字解析版本
|
// TODO: 更换为无异常手写数字解析版本 (charconv也可)
|
||||||
if (lexeme.contains(U'.'))
|
if (lexeme.contains(U'.') || lexeme.contains(U'e'))
|
||||||
{
|
{
|
||||||
// 非整数
|
// 非整数
|
||||||
double d = std::stod(lexeme.toStdString());
|
double d = std::stod(lexeme.toStdString());
|
||||||
@@ -63,23 +63,34 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::uint8_t targetReg = AllocReg();
|
std::uint8_t targetReg = AllocReg();
|
||||||
|
|
||||||
|
if (current->proto->constants.size() >= MAX_CONSTANTS)
|
||||||
|
{
|
||||||
|
return std::unexpected(Error(
|
||||||
|
ErrorType::TooManyConstants,
|
||||||
|
std::format("constant limit exceeded: {}", MAX_CONSTANTS),
|
||||||
|
"How did you write such code? try global variable or split file",
|
||||||
|
makeSourceLocation(lit)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
std::uint16_t kIndex = AddConstant(v);
|
std::uint16_t kIndex = AddConstant(v);
|
||||||
|
|
||||||
Emit(Op::iABx(OpCode::LoadK, targetReg, kIndex));
|
Emit(Op::iABx(OpCode::LoadK, targetReg, kIndex));
|
||||||
return targetReg;
|
return targetReg;
|
||||||
}
|
}
|
||||||
Result<std::uint8_t, Error> Compiler::CompileAssignment(
|
Result<std::uint8_t, Error> Compiler::compileAssignment(
|
||||||
InfixExpr *infix) // 编译赋值,由 CompileInfixExpr调用
|
InfixExpr *infix) // 编译赋值,由 CompileInfixExpr调用
|
||||||
{
|
{
|
||||||
// op必须为 =
|
// op必须为 =
|
||||||
const auto &_lhsReg = CompileLeftValue(infix->left); // 必须为左值对象
|
const auto &_lhsReg = compileLeftValue(infix->left); // 必须为左值对象
|
||||||
if (!_lhsReg)
|
if (!_lhsReg)
|
||||||
{
|
{
|
||||||
return _lhsReg;
|
return _lhsReg;
|
||||||
}
|
}
|
||||||
std::uint8_t lhsReg = *_lhsReg;
|
std::uint8_t lhsReg = *_lhsReg;
|
||||||
|
|
||||||
const auto &_rhsReg = CompileExpr(infix->right);
|
const auto &_rhsReg = compileExpr(infix->right);
|
||||||
std::uint8_t rhsReg = *_rhsReg;
|
std::uint8_t rhsReg = *_rhsReg;
|
||||||
|
|
||||||
FreeReg(rhsReg);
|
FreeReg(rhsReg);
|
||||||
@@ -119,21 +130,21 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
return lhsReg; // 返回赋值的结果,支持连续赋值
|
return lhsReg; // 返回赋值的结果,支持连续赋值
|
||||||
}
|
}
|
||||||
Result<std::uint8_t, Error> Compiler::CompileInfixExpr(
|
Result<std::uint8_t, Error> Compiler::compileInfixExpr(
|
||||||
InfixExpr *infix) // 编译中缀表达式,返回一个存放结果的寄存器 ID
|
InfixExpr *infix) // 编译中缀表达式,返回一个存放结果的寄存器 ID
|
||||||
{
|
{
|
||||||
if (infix->op >= BinaryOperator::Assign && infix->op <= BinaryOperator::BitXorAssign)
|
if (infix->op >= BinaryOperator::Assign && infix->op <= BinaryOperator::BitXorAssign)
|
||||||
{
|
{
|
||||||
return CompileAssignment(infix);
|
return compileAssignment(infix);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &_lhsReg = CompileExpr(infix->left);
|
const auto &_lhsReg = compileExpr(infix->left);
|
||||||
if (!_lhsReg)
|
if (!_lhsReg)
|
||||||
{
|
{
|
||||||
return _lhsReg;
|
return _lhsReg;
|
||||||
}
|
}
|
||||||
std::uint8_t lhsReg = *_lhsReg;
|
std::uint8_t lhsReg = *_lhsReg;
|
||||||
const auto &_rhsReg = CompileExpr(infix->right);
|
const auto &_rhsReg = compileExpr(infix->right);
|
||||||
if (!_rhsReg)
|
if (!_rhsReg)
|
||||||
{
|
{
|
||||||
return _rhsReg;
|
return _rhsReg;
|
||||||
@@ -171,25 +182,52 @@ namespace Fig
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case BinaryOperator::Greater: {
|
||||||
|
Emit(Op::iABC(OpCode::Greater, resultReg, lhsReg, rhsReg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BinaryOperator::GreaterEqual: {
|
||||||
|
Emit(Op::iABC(OpCode::GreaterEqual, resultReg, lhsReg, rhsReg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BinaryOperator::Less: {
|
||||||
|
Emit(Op::iABC(OpCode::Less, resultReg, lhsReg, rhsReg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BinaryOperator::LessEqual: {
|
||||||
|
Emit(Op::iABC(OpCode::LessEqual, resultReg, lhsReg, rhsReg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BinaryOperator::Equal: {
|
||||||
|
Emit(Op::iABC(OpCode::Equal, resultReg, lhsReg, rhsReg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: assert(false && "CompileInfixExpr: op unsupported yet");
|
default: assert(false && "CompileInfixExpr: op unsupported yet");
|
||||||
}
|
}
|
||||||
return resultReg;
|
return resultReg;
|
||||||
}
|
}
|
||||||
Result<std::uint8_t, Error> Compiler::CompileLeftValue(
|
Result<std::uint8_t, Error> Compiler::compileLeftValue(
|
||||||
Expr *expr) // 左值对象,可以是变量、结构体字段或模块对象
|
Expr *expr) // 左值对象,可以是变量、结构体字段或模块对象
|
||||||
{
|
{
|
||||||
switch (expr->type)
|
switch (expr->type)
|
||||||
{
|
{
|
||||||
case AstType::IdentiExpr: return CompileIdentiExpr(static_cast<IdentiExpr *>(expr));
|
case AstType::IdentiExpr:
|
||||||
|
return compileIdentiExpr(static_cast<IdentiExpr *>(expr));
|
||||||
|
// TODO: 数组切片(a[0])或对象属性(a.b)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return std::unexpected(Error(ErrorType::NotAnLvalue,
|
// Analyzer 有漏洞(编译器内部
|
||||||
std::format("`{}` is not a lvalue, expect a valid lvalue", expr->toString()),
|
// 直接崩溃
|
||||||
"none",
|
assert(false && "Compiler Bug: Invalid L-value bypassed Analyzer!");
|
||||||
makeSourceLocation(expr)));
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Result<std::uint8_t, Error> Compiler::CompileExpr(
|
Result<std::uint8_t, Error> Compiler::compileExpr(
|
||||||
Expr *expr) // 编译表达式,必定返回一个存放结果的寄存器 ID
|
Expr *expr) // 编译表达式,必定返回一个存放结果的寄存器 ID
|
||||||
{
|
{
|
||||||
switch (expr->type)
|
switch (expr->type)
|
||||||
@@ -199,12 +237,12 @@ namespace Fig
|
|||||||
case AstType::AstNode: assert(false && "CompileExpr: bad node type"); break;
|
case AstType::AstNode: assert(false && "CompileExpr: bad node type"); break;
|
||||||
|
|
||||||
case AstType::IdentiExpr: {
|
case AstType::IdentiExpr: {
|
||||||
return CompileLeftValue(expr); // 左值直接转换成右值
|
return compileLeftValue(expr); // 左值直接转换成右值
|
||||||
}
|
}
|
||||||
case AstType::LiteralExpr: {
|
case AstType::LiteralExpr: {
|
||||||
LiteralExpr *lit = static_cast<LiteralExpr *>(expr);
|
LiteralExpr *lit = static_cast<LiteralExpr *>(expr);
|
||||||
|
|
||||||
const auto &result = CompileLiteral(lit);
|
auto result = compileLiteral(lit);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
@@ -213,7 +251,7 @@ namespace Fig
|
|||||||
return targetReg;
|
return targetReg;
|
||||||
}
|
}
|
||||||
case AstType::InfixExpr: {
|
case AstType::InfixExpr: {
|
||||||
return CompileInfixExpr(static_cast<InfixExpr *>(expr));
|
return compileInfixExpr(static_cast<InfixExpr *>(expr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,40 +9,40 @@
|
|||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
Result<void, Error> Compiler::CompileVarDecl(VarDecl *varDecl)
|
Result<void, Error> Compiler::compileVarDecl(VarDecl *varDecl)
|
||||||
{
|
{
|
||||||
const String &name = varDecl->name;
|
if (current->freeReg > MAX_LOCALS)
|
||||||
// if (HasLocalInCurrentScope(name))
|
{
|
||||||
// {
|
return std::unexpected(Error(ErrorType::TooManyLocals,
|
||||||
// return std::unexpected(Error(ErrorType::RedeclarationError,
|
std::format("local limit exceeded: {}", MAX_LOCALS),
|
||||||
// std::format("variable `{}` has already defined in this scope", name),
|
"try split function or use arrays/structs...",
|
||||||
// "change its name",
|
makeSourceLocation(varDecl)));
|
||||||
// makeSourceLocation(varDecl)));
|
}
|
||||||
// }
|
|
||||||
std::uint8_t varReg;
|
std::uint8_t varReg;
|
||||||
if (varDecl->initExpr)
|
if (varDecl->initExpr)
|
||||||
{
|
{
|
||||||
const auto &result = CompileExpr(varDecl->initExpr);
|
auto result = compileExpr(varDecl->initExpr);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
}
|
}
|
||||||
std::uint8_t resultReg = *result;
|
std::uint8_t resultReg = *result;
|
||||||
varReg = resultReg; // 复用临时计算结果寄存器
|
varReg = DeclareLocal(varDecl->localId, resultReg); // 复用临时计算结果寄存器
|
||||||
DeclareLocal(varDecl->isPublic, name, varReg);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
varReg = DeclareLocal(varDecl->isPublic, name);
|
varReg = DeclareLocal(varDecl->localId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result<void, Error>();
|
return Result<void, Error>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void, Error> Compiler::CompileBlockStmt(BlockStmt *blockStmt)
|
Result<void, Error> Compiler::compileBlockStmt(BlockStmt *blockStmt)
|
||||||
{
|
{
|
||||||
for (Stmt *stmt : blockStmt->nodes)
|
for (Stmt *stmt : blockStmt->nodes)
|
||||||
{
|
{
|
||||||
const auto &result = CompileStmt(stmt);
|
auto result = compileStmt(stmt);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
@@ -51,7 +51,7 @@ namespace Fig
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void, Error> Compiler::CompileIfStmt(IfStmt *stmt)
|
Result<void, Error> Compiler::compileIfStmt(IfStmt *stmt)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
if cond1
|
if cond1
|
||||||
@@ -97,7 +97,7 @@ namespace Fig
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
std::vector<int> exitJumps; // 所有分支都要跳到最后,收集所有jump最后回填
|
std::vector<int> exitJumps; // 所有分支都要跳到最后,收集所有jump最后回填
|
||||||
const auto &condResult = CompileExpr(stmt->cond);
|
const auto &condResult = compileExpr(stmt->cond);
|
||||||
if (!condResult)
|
if (!condResult)
|
||||||
{
|
{
|
||||||
return std::unexpected(condResult.error());
|
return std::unexpected(condResult.error());
|
||||||
@@ -106,7 +106,7 @@ namespace Fig
|
|||||||
int jumpToNext = EmitJump(OpCode::JmpIfFalse, condReg);
|
int jumpToNext = EmitJump(OpCode::JmpIfFalse, condReg);
|
||||||
FreeReg(condReg);
|
FreeReg(condReg);
|
||||||
|
|
||||||
const auto &blockResult = CompileStmt(stmt->consequent);
|
const auto &blockResult = compileStmt(stmt->consequent);
|
||||||
if (!blockResult)
|
if (!blockResult)
|
||||||
{
|
{
|
||||||
return blockResult;
|
return blockResult;
|
||||||
@@ -117,7 +117,7 @@ namespace Fig
|
|||||||
|
|
||||||
for (auto *elif : stmt->elifs)
|
for (auto *elif : stmt->elifs)
|
||||||
{
|
{
|
||||||
const auto &elifCondResult = CompileExpr(elif->cond);
|
const auto &elifCondResult = compileExpr(elif->cond);
|
||||||
if (!elifCondResult)
|
if (!elifCondResult)
|
||||||
return std::unexpected(elifCondResult.error());
|
return std::unexpected(elifCondResult.error());
|
||||||
std::uint8_t elifCondReg = *elifCondResult;
|
std::uint8_t elifCondReg = *elifCondResult;
|
||||||
@@ -125,7 +125,7 @@ namespace Fig
|
|||||||
jumpToNext = EmitJump(OpCode::JmpIfFalse, elifCondReg);
|
jumpToNext = EmitJump(OpCode::JmpIfFalse, elifCondReg);
|
||||||
FreeReg(elifCondReg);
|
FreeReg(elifCondReg);
|
||||||
|
|
||||||
const auto &blockResult = CompileStmt(elif->consequent);
|
const auto &blockResult = compileStmt(elif->consequent);
|
||||||
if (!blockResult)
|
if (!blockResult)
|
||||||
{
|
{
|
||||||
return blockResult;
|
return blockResult;
|
||||||
@@ -136,7 +136,7 @@ namespace Fig
|
|||||||
|
|
||||||
if (stmt->alternate)
|
if (stmt->alternate)
|
||||||
{
|
{
|
||||||
const auto &result = CompileStmt(stmt->alternate);
|
auto result = compileStmt(stmt->alternate);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
@@ -148,31 +148,65 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
Result<void, Error> Compiler::CompileStmt(Stmt *stmt) // 编译语句
|
|
||||||
|
Result<void, Error> Compiler::compileWhileStmt(WhileStmt *stmt)
|
||||||
{
|
{
|
||||||
if (stmt->type == AstType::ExprStmt)
|
int beginIns = current->proto->code.size() - 1;
|
||||||
|
|
||||||
|
auto condRegResult = compileExpr(stmt->cond);
|
||||||
|
if (!condRegResult)
|
||||||
{
|
{
|
||||||
|
return std::unexpected(condRegResult.error());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint8_t condReg = *condRegResult;
|
||||||
|
|
||||||
|
int exitJump = EmitJump(OpCode::JmpIfFalse, condReg);
|
||||||
|
auto bodyResult = compileBlockStmt(stmt->body);
|
||||||
|
|
||||||
|
if (!bodyResult)
|
||||||
|
{
|
||||||
|
return bodyResult;
|
||||||
|
}
|
||||||
|
Emit(Op::iAsBx(
|
||||||
|
OpCode::Jmp, 0, beginIns - current->proto->code.size())); // 回到开头对condition求值
|
||||||
|
PatchJump(exitJump);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void, Error> Compiler::compileStmt(Stmt *stmt) // 编译语句
|
||||||
|
{
|
||||||
|
switch (stmt->type)
|
||||||
|
{
|
||||||
|
case AstType::ExprStmt: {
|
||||||
ExprStmt *exprStmt = static_cast<ExprStmt *>(stmt);
|
ExprStmt *exprStmt = static_cast<ExprStmt *>(stmt);
|
||||||
Expr *expr = exprStmt->expr;
|
Expr *expr = exprStmt->expr;
|
||||||
const auto &result = CompileExpr(expr);
|
auto result = compileExpr(expr);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
}
|
}
|
||||||
FreeReg(*result);
|
FreeReg(*result);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (stmt->type == AstType::VarDecl)
|
|
||||||
{
|
case AstType::VarDecl: {
|
||||||
return CompileVarDecl(static_cast<VarDecl *>(stmt));
|
return compileVarDecl(static_cast<VarDecl *>(stmt));
|
||||||
}
|
}
|
||||||
else if (stmt->type == AstType::BlockStmt)
|
|
||||||
{
|
case AstType::BlockStmt: {
|
||||||
return CompileBlockStmt(static_cast<BlockStmt *>(stmt));
|
return compileBlockStmt(static_cast<BlockStmt *>(stmt));
|
||||||
}
|
}
|
||||||
else if (stmt->type == AstType::IfStmt)
|
|
||||||
{
|
case AstType::IfStmt: {
|
||||||
return CompileIfStmt(static_cast<IfStmt *>(stmt));
|
return compileIfStmt(static_cast<IfStmt *>(stmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AstType::WhileStmt: {
|
||||||
|
return compileWhileStmt(static_cast<WhileStmt *>(stmt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Result<void, Error>();
|
return Result<void, Error>();
|
||||||
}
|
}
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
@@ -56,6 +56,9 @@ namespace Fig
|
|||||||
case UseUndeclaredIdentifier: return "UseUndeclaredIdentifier";
|
case UseUndeclaredIdentifier: return "UseUndeclaredIdentifier";
|
||||||
case NotAnLvalue: return "NotAnLvalue";
|
case NotAnLvalue: return "NotAnLvalue";
|
||||||
case TypeError: return "TypeError";
|
case TypeError: return "TypeError";
|
||||||
|
|
||||||
|
case TooManyLocals: return "TooManyLocals";
|
||||||
|
case TooManyConstants: return "TooManyConstants";
|
||||||
// default: return "Some one forgot to add case to `ErrorTypeToString`";
|
// default: return "Some one forgot to add case to `ErrorTypeToString`";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ namespace Fig
|
|||||||
UseUndeclaredIdentifier,
|
UseUndeclaredIdentifier,
|
||||||
NotAnLvalue,
|
NotAnLvalue,
|
||||||
TypeError,
|
TypeError,
|
||||||
|
|
||||||
|
// compile errors
|
||||||
|
TooManyLocals,
|
||||||
|
TooManyConstants,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *ErrorTypeToString(ErrorType type);
|
const char *ErrorTypeToString(ErrorType type);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <Error/Error.hpp>
|
#include <Error/Error.hpp>
|
||||||
#include <Token/Token.hpp>
|
|
||||||
#include <Lexer/Lexer.hpp>
|
#include <Lexer/Lexer.hpp>
|
||||||
|
#include <Token/Token.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ int main()
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
const auto &result = lexer.NextToken();
|
auto result = lexer.NextToken();
|
||||||
if (!result.has_value())
|
if (!result.has_value())
|
||||||
{
|
{
|
||||||
ReportError(result.error(), manager);
|
ReportError(result.error(), manager);
|
||||||
|
|||||||
@@ -11,14 +11,16 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
Result<LiteralExpr *, Error> Parser::parseLiteralExpr() // 当前token为literal时调用
|
Result<LiteralExpr *, Error> Parser::parseLiteralExpr() // 当前token为literal时调用
|
||||||
{
|
{
|
||||||
state = State::ParsingLiteralExpr;
|
StateProtector p(this, {State::ParsingLiteralExpr});
|
||||||
|
|
||||||
const Token &literal_token = consumeToken();
|
const Token &literal_token = consumeToken();
|
||||||
LiteralExpr *node = new LiteralExpr(literal_token, makeSourceLocation(literal_token));
|
LiteralExpr *node = new LiteralExpr(literal_token, makeSourceLocation(literal_token));
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
Result<IdentiExpr *, Error> Parser::parseIdentiExpr() // 当前token为Identifier调用
|
Result<IdentiExpr *, Error> Parser::parseIdentiExpr() // 当前token为Identifier调用
|
||||||
{
|
{
|
||||||
state = State::ParsingIdentiExpr;
|
StateProtector p(this, {State::ParsingIdentiExpr});
|
||||||
|
|
||||||
const Token &identifier = consumeToken();
|
const Token &identifier = consumeToken();
|
||||||
IdentiExpr *node = new IdentiExpr(
|
IdentiExpr *node = new IdentiExpr(
|
||||||
srcManager.GetSub(identifier.index, identifier.length), makeSourceLocation(identifier));
|
srcManager.GetSub(identifier.index, identifier.length), makeSourceLocation(identifier));
|
||||||
@@ -27,7 +29,8 @@ namespace Fig
|
|||||||
|
|
||||||
Result<InfixExpr *, Error> Parser::parseInfixExpr(Expr *lhs) // 当前token为 op
|
Result<InfixExpr *, Error> Parser::parseInfixExpr(Expr *lhs) // 当前token为 op
|
||||||
{
|
{
|
||||||
state = State::ParsingInfixExpr;
|
StateProtector p(this, {State::ParsingInfixExpr});
|
||||||
|
|
||||||
const Token &op_token = consumeToken();
|
const Token &op_token = consumeToken();
|
||||||
BinaryOperator op = TokenToBinaryOp(op_token);
|
BinaryOperator op = TokenToBinaryOp(op_token);
|
||||||
BindingPower rbp = GetBinaryOpRBp(op);
|
BindingPower rbp = GetBinaryOpRBp(op);
|
||||||
@@ -45,7 +48,8 @@ namespace Fig
|
|||||||
|
|
||||||
Result<PrefixExpr *, Error> Parser::parsePrefixExpr() // 当前token为op
|
Result<PrefixExpr *, Error> Parser::parsePrefixExpr() // 当前token为op
|
||||||
{
|
{
|
||||||
state = State::ParsingPrefixExpr;
|
StateProtector p(this, {State::ParsingPrefixExpr});
|
||||||
|
|
||||||
const Token &op_token = consumeToken();
|
const Token &op_token = consumeToken();
|
||||||
UnaryOperator op = TokenToUnaryOp(op_token);
|
UnaryOperator op = TokenToUnaryOp(op_token);
|
||||||
|
|
||||||
@@ -64,7 +68,8 @@ namespace Fig
|
|||||||
Result<IndexExpr *, Error> Parser::parseIndexExpr(
|
Result<IndexExpr *, Error> Parser::parseIndexExpr(
|
||||||
Expr *base) // 由 parseExpression调用, 当前token为 `[`
|
Expr *base) // 由 parseExpression调用, 当前token为 `[`
|
||||||
{
|
{
|
||||||
state = State::ParsingIndexExpr;
|
StateProtector p(this, {State::ParsingIndexExpr});
|
||||||
|
|
||||||
const Token &lbracket_token = consumeToken(); // consume `[`
|
const Token &lbracket_token = consumeToken(); // consume `[`
|
||||||
const auto &index_result = parseExpression();
|
const auto &index_result = parseExpression();
|
||||||
|
|
||||||
@@ -89,7 +94,8 @@ namespace Fig
|
|||||||
Result<CallExpr *, Error> Parser::parseCallExpr(
|
Result<CallExpr *, Error> Parser::parseCallExpr(
|
||||||
Expr *callee) // 由 parseExpression调用, 当前token为 `(`
|
Expr *callee) // 由 parseExpression调用, 当前token为 `(`
|
||||||
{
|
{
|
||||||
state = State::ParsingCallExpr;
|
StateProtector p(this, {State::ParsingCallExpr});
|
||||||
|
|
||||||
const Token &lparen_token = consumeToken(); // consume `(`
|
const Token &lparen_token = consumeToken(); // consume `(`
|
||||||
|
|
||||||
FnCallArgs callArgs;
|
FnCallArgs callArgs;
|
||||||
@@ -137,52 +143,8 @@ namespace Fig
|
|||||||
return new CallExpr(callee, callArgs);
|
return new CallExpr(callee, callArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::unordered_set<TokenType> &Parser::getBaseTerminators()
|
Result<Expr *, Error> Parser::parseExpression(BindingPower rbp)
|
||||||
{
|
{
|
||||||
static const std::unordered_set<TokenType> baseTerminators = {TokenType::Semicolon,
|
|
||||||
TokenType::RightParen,
|
|
||||||
TokenType::RightBracket,
|
|
||||||
TokenType::RightBrace,
|
|
||||||
TokenType::Comma,
|
|
||||||
TokenType::EndOfFile};
|
|
||||||
return baseTerminators;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unordered_set<TokenType> &Parser::getTerminators()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
|
|
||||||
Syntax terminators:
|
|
||||||
; ) ] } , EOF
|
|
||||||
*/
|
|
||||||
|
|
||||||
static std::unordered_set<TokenType> terminators(getBaseTerminators());
|
|
||||||
return terminators;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::resetTermintors()
|
|
||||||
{
|
|
||||||
getTerminators() = getBaseTerminators();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Parser::shouldTerminate()
|
|
||||||
{
|
|
||||||
const Token &token = currentToken();
|
|
||||||
const auto &terminators = getTerminators();
|
|
||||||
return terminators.contains(token.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<Expr *, Error> Parser::parseExpression(BindingPower rbp, TokenType stop, TokenType stop2)
|
|
||||||
{
|
|
||||||
if (!getTerminators().contains(stop))
|
|
||||||
{
|
|
||||||
getTerminators().insert(stop);
|
|
||||||
}
|
|
||||||
if (!getTerminators().contains(stop2))
|
|
||||||
{
|
|
||||||
getTerminators().insert(stop2);
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr *lhs = nullptr;
|
Expr *lhs = nullptr;
|
||||||
Token token = currentToken();
|
Token token = currentToken();
|
||||||
|
|
||||||
@@ -191,7 +153,6 @@ namespace Fig
|
|||||||
const auto &lhs_result = parseIdentiExpr();
|
const auto &lhs_result = parseIdentiExpr();
|
||||||
if (!lhs_result)
|
if (!lhs_result)
|
||||||
{
|
{
|
||||||
resetTermintors();
|
|
||||||
return std::unexpected(lhs_result.error());
|
return std::unexpected(lhs_result.error());
|
||||||
}
|
}
|
||||||
lhs = *lhs_result;
|
lhs = *lhs_result;
|
||||||
@@ -201,7 +162,6 @@ namespace Fig
|
|||||||
const auto &lhs_result = parseLiteralExpr();
|
const auto &lhs_result = parseLiteralExpr();
|
||||||
if (!lhs_result)
|
if (!lhs_result)
|
||||||
{
|
{
|
||||||
resetTermintors();
|
|
||||||
return std::unexpected(lhs_result.error());
|
return std::unexpected(lhs_result.error());
|
||||||
}
|
}
|
||||||
lhs = *lhs_result;
|
lhs = *lhs_result;
|
||||||
@@ -211,7 +171,6 @@ namespace Fig
|
|||||||
const auto &lhs_result = parsePrefixExpr();
|
const auto &lhs_result = parsePrefixExpr();
|
||||||
if (!lhs_result)
|
if (!lhs_result)
|
||||||
{
|
{
|
||||||
resetTermintors();
|
|
||||||
return std::unexpected(lhs_result.error());
|
return std::unexpected(lhs_result.error());
|
||||||
}
|
}
|
||||||
lhs = *lhs_result;
|
lhs = *lhs_result;
|
||||||
@@ -222,7 +181,6 @@ namespace Fig
|
|||||||
const auto &expr_result = parseExpression(0);
|
const auto &expr_result = parseExpression(0);
|
||||||
if (!expr_result)
|
if (!expr_result)
|
||||||
{
|
{
|
||||||
resetTermintors();
|
|
||||||
return expr_result;
|
return expr_result;
|
||||||
}
|
}
|
||||||
const Token &rparen_token = consumeToken(); // consume `)`
|
const Token &rparen_token = consumeToken(); // consume `)`
|
||||||
@@ -238,7 +196,6 @@ namespace Fig
|
|||||||
|
|
||||||
if (!lhs)
|
if (!lhs)
|
||||||
{
|
{
|
||||||
resetTermintors();
|
|
||||||
return std::unexpected(Error(ErrorType::ExpectedExpression,
|
return std::unexpected(Error(ErrorType::ExpectedExpression,
|
||||||
"expected expression",
|
"expected expression",
|
||||||
"insert expressions",
|
"insert expressions",
|
||||||
@@ -252,10 +209,6 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (token.type == stop || token.type == stop2)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsTokenOp(token.type /* isBinary = true */)) // 是否为二元运算符
|
if (IsTokenOp(token.type /* isBinary = true */)) // 是否为二元运算符
|
||||||
{
|
{
|
||||||
@@ -268,7 +221,7 @@ namespace Fig
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &result = parseInfixExpr(lhs);
|
auto result = parseInfixExpr(lhs);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
resetTermintors();
|
resetTermintors();
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
@date 2026-02-14
|
@date 2026-02-14
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <Parser/Parser.hpp>
|
#include <Parser/Parser.hpp>
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
@@ -15,7 +14,7 @@ namespace Fig
|
|||||||
Program *program = new Program;
|
Program *program = new Program;
|
||||||
while (!isEOF)
|
while (!isEOF)
|
||||||
{
|
{
|
||||||
const auto &result = parseStatement();
|
auto result = parseStatement();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
@@ -29,4 +28,4 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
};
|
}; // namespace Fig
|
||||||
@@ -41,7 +41,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
return buffer[++index];
|
return buffer[++index];
|
||||||
}
|
}
|
||||||
const auto &result = lexer.NextToken();
|
auto result = lexer.NextToken();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
ReportError(result.error(), srcManager);
|
ReportError(result.error(), srcManager);
|
||||||
@@ -82,7 +82,7 @@ namespace Fig
|
|||||||
size_t peekIndex = index + lookahead;
|
size_t peekIndex = index + lookahead;
|
||||||
while (peekIndex >= buffer.size() && !isEOF)
|
while (peekIndex >= buffer.size() && !isEOF)
|
||||||
{
|
{
|
||||||
const auto &result = lexer.NextToken();
|
auto result = lexer.NextToken();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
ReportError(result.error(), srcManager);
|
ReportError(result.error(), srcManager);
|
||||||
@@ -121,30 +121,35 @@ namespace Fig
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Error makeUnexpectTokenError(const String &stmtType, const String &expect, const Token &tokenGot, std::source_location loc = std::source_location::current())
|
inline Error makeUnexpectTokenError(const String &stmtType,
|
||||||
|
const String &expect,
|
||||||
|
const Token &tokenGot,
|
||||||
|
std::source_location loc = std::source_location::current())
|
||||||
{
|
{
|
||||||
return Error(
|
return Error(ErrorType::SyntaxError,
|
||||||
ErrorType::SyntaxError,
|
std::format("expect '{}' in {}, got `{}`",
|
||||||
std::format("expect '{}' in {}, got `{}`", expect, stmtType, magic_enum::enum_name(tokenGot.type)),
|
expect,
|
||||||
|
stmtType,
|
||||||
|
magic_enum::enum_name(tokenGot.type)),
|
||||||
"none",
|
"none",
|
||||||
makeSourceLocation(tokenGot),
|
makeSourceLocation(tokenGot),
|
||||||
loc
|
loc);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Error makeExpectSemicolonError(std::source_location loc = std::source_location::current())
|
inline Error makeExpectSemicolonError(
|
||||||
|
std::source_location loc = std::source_location::current())
|
||||||
{
|
{
|
||||||
return Error(
|
return Error(ErrorType::SyntaxError,
|
||||||
ErrorType::SyntaxError,
|
|
||||||
"expect ';' after statement",
|
"expect ';' after statement",
|
||||||
"insert ';'",
|
"insert ';'",
|
||||||
makeSourceLocation(currentToken()),
|
makeSourceLocation(currentToken()),
|
||||||
loc
|
loc);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class State : std::uint8_t
|
struct State
|
||||||
|
{
|
||||||
|
enum StateType : std::uint8_t
|
||||||
{
|
{
|
||||||
Standby,
|
Standby,
|
||||||
|
|
||||||
@@ -159,13 +164,103 @@ namespace Fig
|
|||||||
|
|
||||||
ParsingVarDecl,
|
ParsingVarDecl,
|
||||||
ParsingIf,
|
ParsingIf,
|
||||||
|
ParsingWhile,
|
||||||
|
|
||||||
} state;
|
} type = StateType::Standby;
|
||||||
|
std::unordered_set<TokenType> stopAt = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::unordered_set<TokenType> &getBaseTerminators()
|
||||||
|
{
|
||||||
|
static const std::unordered_set<TokenType> baseTerminators = {TokenType::Semicolon,
|
||||||
|
TokenType::RightParen,
|
||||||
|
TokenType::RightBracket,
|
||||||
|
TokenType::RightBrace,
|
||||||
|
TokenType::Comma,
|
||||||
|
TokenType::EndOfFile};
|
||||||
|
return baseTerminators;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<TokenType> &getTerminators() // 返回固定的终止符
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Syntax terminators:
|
||||||
|
; ) ] } , EOF
|
||||||
|
*/
|
||||||
|
|
||||||
|
static std::unordered_set<TokenType> terminators(getBaseTerminators());
|
||||||
|
return terminators;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetTermintors()
|
||||||
|
{
|
||||||
|
getTerminators() = getBaseTerminators();
|
||||||
|
}
|
||||||
|
bool shouldTerminate() // 判断是否终结
|
||||||
|
{
|
||||||
|
const Token &token = currentToken();
|
||||||
|
const auto &terminators = getTerminators();
|
||||||
|
|
||||||
|
if (terminators.contains(token.type))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (auto it = stateStack.rbegin(); it < stateStack.rend(); ++it)
|
||||||
|
{
|
||||||
|
if (it->stopAt.contains(token.type))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynArray<State> stateStack;
|
||||||
|
|
||||||
|
State ¤tState()
|
||||||
|
{
|
||||||
|
return stateStack.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pushState(State _state)
|
||||||
|
{
|
||||||
|
stateStack.push_back(std::move(_state));
|
||||||
|
}
|
||||||
|
|
||||||
|
void popState()
|
||||||
|
{
|
||||||
|
if (!stateStack.empty())
|
||||||
|
{
|
||||||
|
stateStack.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StateProtector
|
||||||
|
{
|
||||||
|
Parser *parser;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StateProtector(Parser *p, const State &newState) : parser(p)
|
||||||
|
{
|
||||||
|
parser->pushState(newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
~StateProtector()
|
||||||
|
{
|
||||||
|
parser->popState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 禁止拷贝
|
||||||
|
StateProtector(const StateProtector &) = delete;
|
||||||
|
StateProtector &operator=(const StateProtector &) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
Parser(Lexer &_lexer, SourceManager &_srcManager, String _fileName) :
|
Parser(Lexer &_lexer, SourceManager &_srcManager, String _fileName) :
|
||||||
lexer(_lexer), srcManager(_srcManager), fileName(std::move(_fileName))
|
lexer(_lexer), srcManager(_srcManager), fileName(std::move(_fileName))
|
||||||
{
|
{
|
||||||
state = State::Standby;
|
pushState(State());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -175,33 +270,33 @@ namespace Fig
|
|||||||
return SourceLocation(SourcePosition(line, column, tok.length),
|
return SourceLocation(SourcePosition(line, column, tok.length),
|
||||||
fileName,
|
fileName,
|
||||||
"[internal parser]",
|
"[internal parser]",
|
||||||
magic_enum::enum_name(state).data());
|
magic_enum::enum_name(currentState().type).data());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expressions */
|
/* Expressions */
|
||||||
Result<LiteralExpr *, Error> parseLiteralExpr(); // 当前token为literal时调用
|
Result<LiteralExpr *, Error> parseLiteralExpr(); // 当前token为literal时调用
|
||||||
Result<IdentiExpr *, Error> parseIdentiExpr(); // 当前token为Identifier调用
|
Result<IdentiExpr *, Error> parseIdentiExpr(); // 当前token为Identifier调用
|
||||||
|
|
||||||
Result<InfixExpr *, Error> parseInfixExpr(Expr *); // 由 parseExpression递归调用, 当前token为op
|
Result<InfixExpr *, Error> parseInfixExpr(
|
||||||
|
Expr *); // 由 parseExpression递归调用, 当前token为op
|
||||||
Result<PrefixExpr *, Error> parsePrefixExpr(); // 由 parseExpression递归调用, 当前token为op
|
Result<PrefixExpr *, Error> parsePrefixExpr(); // 由 parseExpression递归调用, 当前token为op
|
||||||
|
|
||||||
Result<IndexExpr *, Error> parseIndexExpr(Expr *); // 由 parseExpression调用, 当前token为 `[`
|
Result<IndexExpr *, Error> parseIndexExpr(
|
||||||
|
Expr *); // 由 parseExpression调用, 当前token为 `[`
|
||||||
Result<CallExpr *, Error> parseCallExpr(Expr *); // 由 parseExpression调用, 当前token为 `(`
|
Result<CallExpr *, Error> parseCallExpr(Expr *); // 由 parseExpression调用, 当前token为 `(`
|
||||||
|
|
||||||
const std::unordered_set<TokenType> &getBaseTerminators();
|
Result<Expr *, Error> parseExpression(BindingPower = 0);
|
||||||
std::unordered_set<TokenType> &getTerminators(); // 返回固定的终止符
|
|
||||||
void resetTermintors();
|
|
||||||
bool shouldTerminate(); // 判断是否终结
|
|
||||||
|
|
||||||
Result<Expr *, Error> parseExpression(BindingPower = 0, TokenType stop = TokenType::Semicolon, TokenType stop2 = TokenType::Semicolon);
|
|
||||||
|
|
||||||
/* Statements */
|
/* Statements */
|
||||||
Result<BlockStmt *, Error> parseBlockStmt(); // 当前token为 {
|
Result<BlockStmt *, Error> parseBlockStmt(); // 当前token为 {
|
||||||
Result<VarDecl *, Error> parseVarDecl(bool); // 由 parseStatement调用, 当前token为 var
|
Result<VarDecl *, Error> parseVarDecl(bool); // 由 parseStatement调用, 当前token为 var
|
||||||
Result<IfStmt *, Error> parseIfStmt(); // 由 parseStatement调用, 当前token is if
|
Result<IfStmt *, Error> parseIfStmt(); // 由 parseStatement调用, 当前token为 if
|
||||||
|
Result<WhileStmt *, Error> parseWhileStmt(); // 由 parseStatement调用, 当前token为 while
|
||||||
Result<Stmt *, Error> parseStatement();
|
Result<Stmt *, Error> parseStatement();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Result<Program *, Error> Parse();
|
Result<Program *, Error> Parse();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SET_STOP_AT(...) currentState().stopAt = {__VA_ARGS__};
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
@@ -18,7 +18,7 @@ int main()
|
|||||||
|
|
||||||
Lexer lexer(source, fileName);
|
Lexer lexer(source, fileName);
|
||||||
Parser parser(lexer, srcManager, fileName);
|
Parser parser(lexer, srcManager, fileName);
|
||||||
const auto &result = parser.Parse();
|
auto result = parser.Parse();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
ReportError(result.error(), srcManager);
|
ReportError(result.error(), srcManager);
|
||||||
|
|||||||
@@ -19,14 +19,14 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
return std::unexpected(Error(ErrorType::SyntaxError,
|
return std::unexpected(Error(ErrorType::SyntaxError,
|
||||||
"unclosed braces in block stmt",
|
"unclosed braces in block stmt",
|
||||||
"insert `}`",
|
"insert '}'",
|
||||||
location));
|
location));
|
||||||
}
|
}
|
||||||
if (match(TokenType::RightBrace))
|
if (match(TokenType::RightBrace))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const auto &result = parseStatement();
|
auto result = parseStatement();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
@@ -38,7 +38,7 @@ namespace Fig
|
|||||||
Result<VarDecl *, Error> Parser::parseVarDecl(
|
Result<VarDecl *, Error> Parser::parseVarDecl(
|
||||||
bool isPublic) // 由 parseStatement调用, 当前token为 var
|
bool isPublic) // 由 parseStatement调用, 当前token为 var
|
||||||
{
|
{
|
||||||
state = State::ParsingVarDecl;
|
StateProtector p(this, {State::ParsingVarDecl});
|
||||||
|
|
||||||
SourceLocation location = makeSourceLocation(consumeToken()); // consume `var`
|
SourceLocation location = makeSourceLocation(consumeToken()); // consume `var`
|
||||||
|
|
||||||
@@ -52,7 +52,8 @@ namespace Fig
|
|||||||
Expr *typeSpeicifer = nullptr;
|
Expr *typeSpeicifer = nullptr;
|
||||||
if (match(TokenType::Colon)) // `:`
|
if (match(TokenType::Colon)) // `:`
|
||||||
{
|
{
|
||||||
const auto &result = parseExpression(0, TokenType::Assign, TokenType::Walrus);
|
SET_STOP_AT(TokenType::Walrus, TokenType::Assign);
|
||||||
|
auto result = parseExpression(0);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
@@ -64,7 +65,7 @@ namespace Fig
|
|||||||
bool isInfer = false;
|
bool isInfer = false;
|
||||||
if (match(TokenType::Assign))
|
if (match(TokenType::Assign))
|
||||||
{
|
{
|
||||||
const auto &result = parseExpression();
|
auto result = parseExpression();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
@@ -75,14 +76,13 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
if (typeSpeicifer) // 指定了类型同时使用 :=
|
if (typeSpeicifer) // 指定了类型同时使用 :=
|
||||||
{
|
{
|
||||||
return std::unexpected(Error(
|
return std::unexpected(Error(ErrorType::SyntaxError,
|
||||||
ErrorType::SyntaxError,
|
|
||||||
"used type infer but specifying the type",
|
"used type infer but specifying the type",
|
||||||
"change `:=` to '='",
|
"change `:=` to '='",
|
||||||
makeSourceLocation(prevToken()) // :=
|
makeSourceLocation(prevToken()) // :=
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
const auto &result = parseExpression();
|
auto result = parseExpression();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
@@ -100,14 +100,16 @@ namespace Fig
|
|||||||
|
|
||||||
Result<IfStmt *, Error> Parser::parseIfStmt() // 由 parseStatement调用, 当前token is if
|
Result<IfStmt *, Error> Parser::parseIfStmt() // 由 parseStatement调用, 当前token is if
|
||||||
{
|
{
|
||||||
state = State::ParsingIf;
|
StateProtector p(this, {State::ParsingIf});
|
||||||
|
|
||||||
SourceLocation location = makeSourceLocation(consumeToken()); // consume `if`
|
SourceLocation location = makeSourceLocation(consumeToken()); // consume `if`
|
||||||
|
|
||||||
Expr *cond = nullptr;
|
Expr *cond = nullptr;
|
||||||
if (match(TokenType::LeftParen)) // match and consume `(`
|
if (match(TokenType::LeftParen)) // match and consume `(`
|
||||||
{
|
{
|
||||||
const Token &lpToken = prevToken();
|
const Token &lpToken = prevToken();
|
||||||
const auto &result = parseExpression(0, TokenType::RightParen, TokenType::LeftBrace);
|
SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace);
|
||||||
|
const auto &result = parseExpression(0);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
@@ -124,21 +126,21 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto &result = parseExpression(0, TokenType::LeftBrace);
|
SET_STOP_AT(TokenType::LeftBrace);
|
||||||
|
auto result = parseExpression(0);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
}
|
}
|
||||||
cond = *result;
|
cond = *result;
|
||||||
}
|
}
|
||||||
state = State::ParsingIf;
|
|
||||||
|
|
||||||
if (currentToken().type != TokenType::LeftBrace)
|
if (currentToken().type != TokenType::LeftBrace)
|
||||||
{
|
{
|
||||||
return std::unexpected(
|
return std::unexpected(
|
||||||
makeUnexpectTokenError("IfStmt", "LeftBrace `{`", currentToken()));
|
makeUnexpectTokenError("IfStmt", "LeftBrace `{`", currentToken()));
|
||||||
}
|
}
|
||||||
const auto &result = parseBlockStmt();
|
auto result = parseBlockStmt();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
@@ -167,13 +169,13 @@ namespace Fig
|
|||||||
if (match(TokenType::LeftParen)) // `(`
|
if (match(TokenType::LeftParen)) // `(`
|
||||||
{
|
{
|
||||||
const Token &lpToken = prevToken();
|
const Token &lpToken = prevToken();
|
||||||
const auto &result =
|
|
||||||
parseExpression(0, TokenType::RightParen, TokenType::LeftBrace);
|
SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace);
|
||||||
|
const auto &result = parseExpression(0);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
}
|
}
|
||||||
state = State::ParsingIf;
|
|
||||||
if (!match(TokenType::RightParen))
|
if (!match(TokenType::RightParen))
|
||||||
{
|
{
|
||||||
delete *result;
|
delete *result;
|
||||||
@@ -186,12 +188,12 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto &result = parseExpression(0, TokenType::LeftBrace);
|
SET_STOP_AT(TokenType::LeftBrace);
|
||||||
|
auto result = parseExpression(0);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
}
|
}
|
||||||
state = State::ParsingIf;
|
|
||||||
cond = *result;
|
cond = *result;
|
||||||
}
|
}
|
||||||
if (currentToken().type != TokenType::LeftBrace)
|
if (currentToken().type != TokenType::LeftBrace)
|
||||||
@@ -199,12 +201,11 @@ namespace Fig
|
|||||||
return std::unexpected(
|
return std::unexpected(
|
||||||
makeUnexpectTokenError("ElseIfStmt", "LeftBrace `{`", currentToken()));
|
makeUnexpectTokenError("ElseIfStmt", "LeftBrace `{`", currentToken()));
|
||||||
}
|
}
|
||||||
const auto &result = parseBlockStmt();
|
auto result = parseBlockStmt();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
}
|
}
|
||||||
state = State::ParsingIf;
|
|
||||||
BlockStmt *consequent = *result;
|
BlockStmt *consequent = *result;
|
||||||
ElseIfStmt *elif = new ElseIfStmt(cond, consequent, elseLocation);
|
ElseIfStmt *elif = new ElseIfStmt(cond, consequent, elseLocation);
|
||||||
elifs.push_back(elif);
|
elifs.push_back(elif);
|
||||||
@@ -224,12 +225,11 @@ namespace Fig
|
|||||||
return std::unexpected(
|
return std::unexpected(
|
||||||
makeUnexpectTokenError("ElseStmt", "LeftBrace `{`", currentToken()));
|
makeUnexpectTokenError("ElseStmt", "LeftBrace `{`", currentToken()));
|
||||||
}
|
}
|
||||||
const auto &result = parseBlockStmt();
|
auto result = parseBlockStmt();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
}
|
}
|
||||||
state = State::ParsingIf;
|
|
||||||
alternate = *result;
|
alternate = *result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,9 +237,68 @@ namespace Fig
|
|||||||
return ifStmt;
|
return ifStmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<WhileStmt *, Error> Parser::parseWhileStmt() // 由 parseStatement调用, 当前token为 while
|
||||||
|
{
|
||||||
|
StateProtector p(this, {State::ParsingWhile});
|
||||||
|
|
||||||
|
SourceLocation location = makeSourceLocation(consumeToken()); // consume `while`
|
||||||
|
|
||||||
|
Expr *cond = nullptr;
|
||||||
|
if (match(TokenType::LeftParen))
|
||||||
|
{
|
||||||
|
const Token &lpToken = prevToken();
|
||||||
|
SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace);
|
||||||
|
|
||||||
|
auto result = parseExpression();
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return std::unexpected(result.error());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!match(TokenType::RightParen))
|
||||||
|
{
|
||||||
|
delete *result;
|
||||||
|
return std::unexpected(Error(ErrorType::SyntaxError,
|
||||||
|
"unclosed parenthese in while condition",
|
||||||
|
"insert ')'",
|
||||||
|
makeSourceLocation(lpToken)));
|
||||||
|
}
|
||||||
|
cond = *result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SET_STOP_AT(TokenType::LeftBrace);
|
||||||
|
auto result = parseExpression();
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return std::unexpected(result.error());
|
||||||
|
}
|
||||||
|
cond = *result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentToken().type != TokenType::LeftBrace)
|
||||||
|
{
|
||||||
|
delete cond;
|
||||||
|
return std::unexpected(
|
||||||
|
makeUnexpectTokenError("while stmt", "left brace '{'", currentToken()));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = parseBlockStmt();
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
delete cond;
|
||||||
|
return std::unexpected(result.error());
|
||||||
|
}
|
||||||
|
BlockStmt *body = *result;
|
||||||
|
|
||||||
|
WhileStmt *whileStmt = new WhileStmt(cond, body, location);
|
||||||
|
return whileStmt;
|
||||||
|
}
|
||||||
|
|
||||||
Result<Stmt *, Error> Parser::parseStatement()
|
Result<Stmt *, Error> Parser::parseStatement()
|
||||||
{
|
{
|
||||||
state = State::Standby;
|
StateProtector p(this, {State::Standby});
|
||||||
|
|
||||||
if (currentToken().type == TokenType::Public)
|
if (currentToken().type == TokenType::Public)
|
||||||
{
|
{
|
||||||
consumeToken(); // consume `public`
|
consumeToken(); // consume `public`
|
||||||
@@ -247,20 +306,38 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
return parseVarDecl(true);
|
return parseVarDecl(true);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return std::unexpected(
|
||||||
|
makeUnexpectTokenError("public", "var/const/func/struct", currentToken()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentToken().type == TokenType::LeftBrace)
|
||||||
|
{
|
||||||
|
return parseBlockStmt();
|
||||||
|
}
|
||||||
|
|
||||||
if (currentToken().type == TokenType::Variable)
|
if (currentToken().type == TokenType::Variable)
|
||||||
{
|
{
|
||||||
return parseVarDecl(false);
|
return parseVarDecl(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentToken().type == TokenType::If)
|
if (currentToken().type == TokenType::If)
|
||||||
{
|
{
|
||||||
return parseIfStmt();
|
return parseIfStmt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentToken().type == TokenType::While)
|
||||||
|
{
|
||||||
|
return parseWhileStmt();
|
||||||
|
}
|
||||||
|
|
||||||
if (isEOF)
|
if (isEOF)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &expr_result = parseExpression();
|
const auto &expr_result = parseExpression();
|
||||||
if (!expr_result)
|
if (!expr_result)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
Result<void, Error> Analyzer::analyzeVarDecl(VarDecl *stmt)
|
Result<void, Error> Analyzer::analyzeVarDecl(VarDecl *stmt)
|
||||||
{
|
{
|
||||||
if (env.Resolve(stmt->name) != std::nullopt)
|
auto sym = env.Resolve(stmt->name);
|
||||||
|
if (sym != std::nullopt && sym->depth == env.GetDepth())
|
||||||
{
|
{
|
||||||
return std::unexpected(Error(ErrorType::RedeclarationError,
|
return std::unexpected(Error(ErrorType::RedeclarationError,
|
||||||
std::format("variable `{}` has already defined in this scope", stmt->name),
|
std::format("variable `{}` has already defined in this scope", stmt->name),
|
||||||
@@ -50,7 +51,7 @@ namespace Fig
|
|||||||
"none",
|
"none",
|
||||||
makeSourceLocation(stmt->initExpr)));
|
makeSourceLocation(stmt->initExpr)));
|
||||||
}
|
}
|
||||||
env.Define(stmt->name, declaredType, stmt->isPublic, false);
|
stmt->localId = env.Define(stmt->name, declaredType, stmt->isPublic, false);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,12 +64,11 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
if (stmt->cond->resolvedType != TypeTag::Any && stmt->cond->resolvedType != TypeTag::Bool)
|
if (stmt->cond->resolvedType != TypeTag::Any && stmt->cond->resolvedType != TypeTag::Bool)
|
||||||
{
|
{
|
||||||
return std::unexpected(Error(
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
ErrorType::TypeError,
|
std::format("if condition must be boolean, got `{}`",
|
||||||
std::format("if condition must be boolean, got `{}`", magic_enum::enum_name(stmt->cond->resolvedType)),
|
magic_enum::enum_name(stmt->cond->resolvedType)),
|
||||||
"ensure condition is boolean",
|
"ensure condition is boolean",
|
||||||
makeSourceLocation(stmt->cond)
|
makeSourceLocation(stmt->cond)));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
auto consequentRes = analyzeStmt(stmt->consequent);
|
auto consequentRes = analyzeStmt(stmt->consequent);
|
||||||
if (!consequentRes)
|
if (!consequentRes)
|
||||||
@@ -106,6 +106,31 @@ namespace Fig
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<void, Error> Analyzer::analyzeWhileStmt(WhileStmt *stmt)
|
||||||
|
{
|
||||||
|
auto condRes = analyzeExpr(stmt->cond);
|
||||||
|
if (!condRes)
|
||||||
|
{
|
||||||
|
return condRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stmt->cond->resolvedType != TypeTag::Any && stmt->cond->resolvedType != TypeTag::Bool)
|
||||||
|
{
|
||||||
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
|
std::format("while condition must be boolean, got `{}`",
|
||||||
|
magic_enum::enum_name(stmt->cond->resolvedType)),
|
||||||
|
"ensure condition is boolean",
|
||||||
|
makeSourceLocation(stmt->cond)));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bodyRes = analyzeStmt(stmt->body);
|
||||||
|
if (!bodyRes)
|
||||||
|
{
|
||||||
|
return bodyRes;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
Result<void, Error> Analyzer::analyzeIdentiExpr(IdentiExpr *expr)
|
Result<void, Error> Analyzer::analyzeIdentiExpr(IdentiExpr *expr)
|
||||||
{
|
{
|
||||||
auto sym = env.Resolve(expr->name);
|
auto sym = env.Resolve(expr->name);
|
||||||
@@ -117,8 +142,11 @@ namespace Fig
|
|||||||
makeSourceLocation(expr)));
|
makeSourceLocation(expr)));
|
||||||
}
|
}
|
||||||
// TODO: 引入 Module 跨文件 import,检查 isPublic
|
// TODO: 引入 Module 跨文件 import,检查 isPublic
|
||||||
|
expr->localId = sym->localId;
|
||||||
|
|
||||||
expr->resolvedType = sym->type;
|
expr->resolvedType = sym->type;
|
||||||
expr->resolvedDepth = sym->depth;
|
expr->resolvedDepth = sym->depth;
|
||||||
|
expr->isGlobal = (sym->depth == 0);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -138,7 +166,7 @@ namespace Fig
|
|||||||
|
|
||||||
switch (expr->op)
|
switch (expr->op)
|
||||||
{
|
{
|
||||||
// 1. 算术族 (+, -, *, /, **)
|
// 算术族 (+, -, *, /, **)
|
||||||
case BinaryOperator::Add:
|
case BinaryOperator::Add:
|
||||||
if (lType == TypeTag::String && rType == TypeTag::String)
|
if (lType == TypeTag::String && rType == TypeTag::String)
|
||||||
{
|
{
|
||||||
@@ -172,7 +200,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 2. 整数特化族 (%, &, |, ^, <<, >>)
|
// 整数特化族 (%, &, |, ^, <<, >>)
|
||||||
case BinaryOperator::Modulo:
|
case BinaryOperator::Modulo:
|
||||||
case BinaryOperator::BitAnd:
|
case BinaryOperator::BitAnd:
|
||||||
case BinaryOperator::BitOr:
|
case BinaryOperator::BitOr:
|
||||||
@@ -196,8 +224,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// 比较族 (==, !=, <, >, <=, >=)
|
||||||
// 3. 比较族 (==, !=, <, >, <=, >=)
|
|
||||||
|
|
||||||
case BinaryOperator::Equal:
|
case BinaryOperator::Equal:
|
||||||
case BinaryOperator::NotEqual:
|
case BinaryOperator::NotEqual:
|
||||||
@@ -206,7 +233,8 @@ namespace Fig
|
|||||||
case BinaryOperator::LessEqual:
|
case BinaryOperator::LessEqual:
|
||||||
case BinaryOperator::GreaterEqual:
|
case BinaryOperator::GreaterEqual:
|
||||||
case BinaryOperator::Is:
|
case BinaryOperator::Is:
|
||||||
if (lType != TypeTag::Any && rType != TypeTag::Any && lType != rType) // lType == rType放行
|
if (lType != TypeTag::Any && rType != TypeTag::Any
|
||||||
|
&& lType != rType) // lType == rType放行
|
||||||
{
|
{
|
||||||
if (!((lType == TypeTag::Int && rType == TypeTag::Double)
|
if (!((lType == TypeTag::Int && rType == TypeTag::Double)
|
||||||
|| (lType == TypeTag::Double && rType == TypeTag::Int)))
|
|| (lType == TypeTag::Double && rType == TypeTag::Int)))
|
||||||
@@ -225,8 +253,7 @@ namespace Fig
|
|||||||
expr->resolvedType = TypeTag::Bool;
|
expr->resolvedType = TypeTag::Bool;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// 逻辑族 (&&, ||)
|
||||||
// 4. 逻辑族 (&&, ||)
|
|
||||||
case BinaryOperator::LogicalAnd:
|
case BinaryOperator::LogicalAnd:
|
||||||
case BinaryOperator::LogicalOr:
|
case BinaryOperator::LogicalOr:
|
||||||
if (lType == TypeTag::Bool && rType == TypeTag::Bool)
|
if (lType == TypeTag::Bool && rType == TypeTag::Bool)
|
||||||
@@ -246,8 +273,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// 纯赋值与复合赋值族 (=, +=, -=, ...)
|
||||||
// 5. 纯赋值与复合赋值族 (=, +=, -=, ...)
|
|
||||||
case BinaryOperator::Assign:
|
case BinaryOperator::Assign:
|
||||||
case BinaryOperator::AddAssign:
|
case BinaryOperator::AddAssign:
|
||||||
case BinaryOperator::SubAssign:
|
case BinaryOperator::SubAssign:
|
||||||
@@ -258,8 +284,7 @@ namespace Fig
|
|||||||
// 左侧必须是合法的 L-Value
|
// 左侧必须是合法的 L-Value
|
||||||
if (!isValidLvalue(expr->left))
|
if (!isValidLvalue(expr->left))
|
||||||
{
|
{
|
||||||
return std::unexpected(
|
return std::unexpected(Error(ErrorType::NotAnLvalue,
|
||||||
Error(ErrorType::NotAnLvalue,
|
|
||||||
"invalid assignment target",
|
"invalid assignment target",
|
||||||
"left side must be a variable, property, or indexable target",
|
"left side must be a variable, property, or indexable target",
|
||||||
makeSourceLocation(expr->left) // 错误精准定位到左侧节点
|
makeSourceLocation(expr->left) // 错误精准定位到左侧节点
|
||||||
@@ -283,8 +308,7 @@ namespace Fig
|
|||||||
expr->resolvedType = lType;
|
expr->resolvedType = lType;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// 成员访问 (.)
|
||||||
// 6. 成员访问 (.)
|
|
||||||
case BinaryOperator::MemberAccess:
|
case BinaryOperator::MemberAccess:
|
||||||
if (lType != TypeTag::Struct && lType != TypeTag::Any)
|
if (lType != TypeTag::Struct && lType != TypeTag::Any)
|
||||||
{
|
{
|
||||||
@@ -293,6 +317,15 @@ namespace Fig
|
|||||||
"check if the left side evaluates to an object",
|
"check if the left side evaluates to an object",
|
||||||
makeSourceLocation(expr->left)));
|
makeSourceLocation(expr->left)));
|
||||||
}
|
}
|
||||||
|
if (expr->right->type != AstType::IdentiExpr)
|
||||||
|
{
|
||||||
|
return std::unexpected(Error(
|
||||||
|
ErrorType::SyntaxError,
|
||||||
|
std::format("expect field name after member access '.', got {}", expr->right->toString()),
|
||||||
|
"none",
|
||||||
|
makeSourceLocation(expr->right)
|
||||||
|
));
|
||||||
|
}
|
||||||
expr->resolvedType = TypeTag::Any;
|
expr->resolvedType = TypeTag::Any;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -336,6 +369,10 @@ namespace Fig
|
|||||||
return analyzeIfStmt(static_cast<IfStmt *>(stmt));
|
return analyzeIfStmt(static_cast<IfStmt *>(stmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AstType::WhileStmt: {
|
||||||
|
return analyzeWhileStmt(static_cast<WhileStmt *>(stmt));
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: 其他语句分析
|
// TODO: 其他语句分析
|
||||||
|
|
||||||
// default:
|
// default:
|
||||||
@@ -356,16 +393,12 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
case AstType::LiteralExpr: {
|
case AstType::LiteralExpr: {
|
||||||
auto *lit = static_cast<LiteralExpr *>(expr);
|
auto *lit = static_cast<LiteralExpr *>(expr);
|
||||||
switch(lit->token.type)
|
switch (lit->token.type)
|
||||||
{
|
{
|
||||||
case TokenType::LiteralTrue:
|
case TokenType::LiteralTrue:
|
||||||
case TokenType::LiteralFalse:
|
case TokenType::LiteralFalse: lit->resolvedType = TypeTag::Bool; break;
|
||||||
lit->resolvedType = TypeTag::Bool;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TokenType::LiteralNull:
|
case TokenType::LiteralNull: lit->resolvedType = TypeTag::Null; break;
|
||||||
lit->resolvedType = TypeTag::Null;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TokenType::LiteralNumber: {
|
case TokenType::LiteralNumber: {
|
||||||
const String &lexeme = manager.GetSub(lit->token.index, lit->token.length);
|
const String &lexeme = manager.GetSub(lit->token.index, lit->token.length);
|
||||||
@@ -385,10 +418,11 @@ namespace Fig
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default: {
|
||||||
lit->resolvedType = TypeTag::Any;
|
lit->resolvedType = TypeTag::Any;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ namespace Fig
|
|||||||
|
|
||||||
Result<void, Error> analyzeVarDecl(VarDecl *);
|
Result<void, Error> analyzeVarDecl(VarDecl *);
|
||||||
Result<void, Error> analyzeIfStmt(IfStmt *);
|
Result<void, Error> analyzeIfStmt(IfStmt *);
|
||||||
|
Result<void, Error> analyzeWhileStmt(WhileStmt *);
|
||||||
|
|
||||||
Result<void, Error> analyzeIdentiExpr(IdentiExpr *);
|
Result<void, Error> analyzeIdentiExpr(IdentiExpr *);
|
||||||
Result<void, Error> analyzeInfixExpr(InfixExpr *);
|
Result<void, Error> analyzeInfixExpr(InfixExpr *);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ int main()
|
|||||||
Lexer lexer(manager.GetSource(), fileName);
|
Lexer lexer(manager.GetSource(), fileName);
|
||||||
Parser parser(lexer, manager, fileName);
|
Parser parser(lexer, manager, fileName);
|
||||||
|
|
||||||
const auto &result = parser.Parse();
|
auto result = parser.Parse();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
ReportError(result.error(), manager);
|
ReportError(result.error(), manager);
|
||||||
|
|||||||
@@ -7,15 +7,15 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Sema/Type.hpp>
|
|
||||||
#include <Deps/Deps.hpp>
|
#include <Deps/Deps.hpp>
|
||||||
#include <Error/Error.hpp>
|
#include <Error/Error.hpp>
|
||||||
|
#include <Sema/Type.hpp>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
|
|
||||||
// 记录在 Analyzer 中的符号元数据
|
// 记录在 Analyzer 中的符号元数据
|
||||||
struct Symbol
|
struct Symbol
|
||||||
{
|
{
|
||||||
@@ -24,41 +24,108 @@ namespace Fig
|
|||||||
bool isPublic;
|
bool isPublic;
|
||||||
int depth; // 词法作用域深度
|
int depth; // 词法作用域深度
|
||||||
bool isConstant; // 是否是 const 声明的不可变常量 (用于报错: 尝试修改常量)
|
bool isConstant; // 是否是 const 声明的不可变常量 (用于报错: 尝试修改常量)
|
||||||
|
|
||||||
|
int localId = -1; // Analyzer 虚拟槽位分配
|
||||||
|
};
|
||||||
|
|
||||||
|
// 作用域回档水位线
|
||||||
|
struct ScopeWatermark
|
||||||
|
{
|
||||||
|
std::size_t symbolCount;
|
||||||
|
int savedLocalId;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 语义分析函数上下文 (隔离局部变量 ID 空间)
|
||||||
|
struct SemaFuncState
|
||||||
|
{
|
||||||
|
SemaFuncState *enclosing = nullptr;
|
||||||
|
int currentDepth = 0;
|
||||||
|
int nextLocalId = 0;
|
||||||
|
DynArray<ScopeWatermark> scopeStack;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Environment
|
class Environment
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
DynArray<Symbol> symbols;
|
DynArray<Symbol> symbols;
|
||||||
int currentDepth = 0;
|
SemaFuncState *current = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Environment()
|
||||||
|
{
|
||||||
|
current = new SemaFuncState();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Environment()
|
||||||
|
{
|
||||||
|
while (current)
|
||||||
|
{
|
||||||
|
SemaFuncState *prev = current->enclosing;
|
||||||
|
delete current;
|
||||||
|
current = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 函数边界控
|
||||||
|
|
||||||
|
void EnterFunction()
|
||||||
|
{
|
||||||
|
SemaFuncState *newState = new SemaFuncState();
|
||||||
|
newState->enclosing = current;
|
||||||
|
current = newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaveFunction()
|
||||||
|
{
|
||||||
|
assert(current && "Environment: Unmatched LeaveFunction");
|
||||||
|
SemaFuncState *oldState = current;
|
||||||
|
current = oldState->enclosing;
|
||||||
|
delete oldState;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 词法作用域控制
|
||||||
|
|
||||||
void EnterScope()
|
void EnterScope()
|
||||||
{
|
{
|
||||||
currentDepth++;
|
current->currentDepth++;
|
||||||
|
current->scopeStack.push_back({symbols.size(), current->nextLocalId});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeaveScope()
|
void LeaveScope()
|
||||||
{
|
{
|
||||||
while (!symbols.empty() && symbols.back().depth > currentDepth)
|
assert(current->currentDepth > 0 && "Environment: Unmatched LeaveScope");
|
||||||
|
current->currentDepth--;
|
||||||
|
|
||||||
|
assert(!current->scopeStack.empty());
|
||||||
|
ScopeWatermark archive = current->scopeStack.back();
|
||||||
|
current->scopeStack.pop_back();
|
||||||
|
|
||||||
|
// 物理截断符号表,回滚槽位发号器以复用物理寄存器
|
||||||
|
while (symbols.size() > archive.symbolCount)
|
||||||
{
|
{
|
||||||
symbols.pop_back();
|
symbols.pop_back();
|
||||||
}
|
}
|
||||||
currentDepth--;
|
current->nextLocalId = archive.savedLocalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册符号, 调用前确保无重复 (内部assert)
|
// 符号操作
|
||||||
void Define(const String &name, TypeTag type, bool isPublic, bool isConst)
|
|
||||||
|
// 注册符号, 返回分配的 localId。调用前内部执行同级作用域重定义断言
|
||||||
|
int Define(const String &name, TypeTag type, bool isPublic, bool isConst)
|
||||||
{
|
{
|
||||||
for (auto it = symbols.rbegin(); it != symbols.rend(); ++it)
|
for (auto it = symbols.rbegin(); it != symbols.rend(); ++it)
|
||||||
{
|
{
|
||||||
if (it->depth < currentDepth)
|
if (it->depth < current->currentDepth)
|
||||||
break;
|
break;
|
||||||
if (it->name == name)
|
if (it->name == name)
|
||||||
{
|
{
|
||||||
assert(false && "Environment.Define: redefinition");
|
assert(false && "Environment.Define: redefinition");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
symbols.push_back({name, type, isPublic, currentDepth, isConst});
|
|
||||||
|
int allocatedId = current->nextLocalId++;
|
||||||
|
symbols.push_back({name, type, isPublic, current->currentDepth, isConst, allocatedId});
|
||||||
|
return allocatedId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析符号。找不到返回 nullopt
|
// 解析符号。找不到返回 nullopt
|
||||||
@@ -74,7 +141,7 @@ namespace Fig
|
|||||||
|
|
||||||
int GetDepth() const
|
int GetDepth() const
|
||||||
{
|
{
|
||||||
return currentDepth;
|
return current->currentDepth;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace Fig
|
} // namespace Fig
|
||||||
@@ -3,13 +3,15 @@
|
|||||||
#include <Deps/Deps.hpp>
|
#include <Deps/Deps.hpp>
|
||||||
#include <Lexer/Lexer.hpp>
|
#include <Lexer/Lexer.hpp>
|
||||||
#include <Parser/Parser.hpp>
|
#include <Parser/Parser.hpp>
|
||||||
#include <SourceManager/SourceManager.hpp>
|
|
||||||
#include <Sema/Analyzer.hpp>
|
#include <Sema/Analyzer.hpp>
|
||||||
|
#include <SourceManager/SourceManager.hpp>
|
||||||
#include <VM/VM.hpp>
|
#include <VM/VM.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <print>
|
#include <print>
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@@ -47,7 +49,6 @@ int main()
|
|||||||
}
|
}
|
||||||
std::cout << "analyzer: Program OK, PASSED\n";
|
std::cout << "analyzer: Program OK, PASSED\n";
|
||||||
|
|
||||||
|
|
||||||
Compiler compiler(fileName, manager);
|
Compiler compiler(fileName, manager);
|
||||||
const auto &proto_result = compiler.Compile(program);
|
const auto &proto_result = compiler.Compile(program);
|
||||||
if (!proto_result)
|
if (!proto_result)
|
||||||
@@ -70,7 +71,7 @@ int main()
|
|||||||
|
|
||||||
VM vm;
|
VM vm;
|
||||||
|
|
||||||
const auto &result_ = vm.Execute(proto);
|
auto result_ = vm.Execute(proto);
|
||||||
if (!result_)
|
if (!result_)
|
||||||
{
|
{
|
||||||
ReportError(result_.error(), manager);
|
ReportError(result_.error(), manager);
|
||||||
|
|||||||
Reference in New Issue
Block a user