feat: 添加“while 语句”支持,并对解析器进行重构以处理控制流相关内容

- 引入了 WhileStmt 结构来表示 while 循环语句。
- 在解析器中实现了对 while 语句的解析逻辑。
- 在分析器中为 while 语句添加了语义分析。
- 重构了现有的解析器方法,以利用 StateProtector 进行状态管理。
- 更新了对各种表达式和语句的错误处理。
- 移除了未使用的终止符管理方法,并简化了表达式解析。
- 将 FigLSPServer.cpp 重命名为 LSPServer.cpp,并调整了构建配置。
- 增强了重复声明和类型错误的错误报告。
- 在多个文件中改进了代码格式和一致性。
This commit is contained in:
2026-02-25 17:31:00 +08:00
parent b7bb889676
commit a0fb8cdffb
25 changed files with 670 additions and 355 deletions

View File

@@ -16,4 +16,5 @@
#include <Ast/Stmt/ExprStmt.hpp>
#include <Ast/Stmt/IfStmt.hpp>
#include <Ast/Stmt/VarDecl.hpp>
#include <Ast/Stmt/VarDecl.hpp>
#include <Ast/Stmt/WhileStmt.hpp>

View File

@@ -36,7 +36,8 @@ namespace Fig
ExprStmt, // 表达式语句,如 println(1)
VarDecl, // 变量声明
IfStmt, // If语句
ElseIfStmt, // ElseIf语句不准悬空
ElseIfStmt, // ElseIf语句不准悬空平铺式else if
WhileStmt, // while语句
};
struct AstNode
{

View File

@@ -16,9 +16,17 @@ namespace Fig
{
String name;
// Analyzer槽位,存储具体深度
int resolvedDepth = -1; // 代表未解析
bool isGlobal = false; // 是否全局/对外公开 (isPublic)
// Analyzer槽位
// 寻址空间
bool isGlobal = false; // 是否全局, 全局变量存哈希/堆
// 仅 isGlobal = false 有效
int resolvedDepth = -1; // 用于获取闭包上值, -1 代表未解析
// 栈内槽位
int localId = -1; // 局部变量id, -1 未解析
IdentiExpr()
{

View File

@@ -19,6 +19,8 @@ namespace Fig
bool isInfer; // 是否用了 := 类型推断
Expr *initExpr;
int localId = -1;
VarDecl()
{
type = AstType::VarDecl;

View 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

View File

@@ -16,7 +16,7 @@ namespace Fig
for (Stmt *stmt : program->nodes)
{
const auto &result = CompileStmt(static_cast<Stmt *>(stmt));
auto result = compileStmt(static_cast<Stmt *>(stmt));
if (!result)
{
return std::unexpected(result.error());

View File

@@ -29,12 +29,14 @@ namespace Fig
struct LocalVar
{
bool isPublic; // 是否向上级/同级其他域公开
String name;
std::uint8_t reg; // 寄存器(相对 frame base 的寄存器 id)
int depth; // 作用域深度
int localId; // AST 传来的纯数字 ID
std::uint8_t reg; // 分配到的物理寄存器 ID
int depth; // 物理作用域深度(用于 EndScope 释放寄存器)
};
static constexpr int MAX_LOCALS = 250;
static constexpr int MAX_CONSTANTS = UINT16_MAX;
// 任何跨函数、跨模块的编译,都压入弹出这个 State
struct FuncState
{
@@ -46,9 +48,12 @@ namespace Fig
int scopeDepth = 0;
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)
{
proto = new Proto();
std::fill_n(fastRegMap, 256, UINT8_MAX); // 255代表未分配
}
// 注意:这里不 delete proto因为 proto 是要作为编译产物吐出去的
};
@@ -100,7 +105,7 @@ namespace Fig
std::uint8_t AllocReg()
{
if (current->freeReg >= 250)
if (current->freeReg >= 255)
{
assert(false && "Register overflow!");
}
@@ -137,6 +142,13 @@ namespace Fig
std::uint16_t AddConstant(Value v)
{
// 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);
return static_cast<std::uint16_t>(current->proto->constants.size() - 1);
}
@@ -156,73 +168,18 @@ namespace Fig
}
}
bool HasLocalInCurrentScope(const String &name)
{
// 逆向查重
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 DeclareLocal(int localId)
{
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;
}
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;
}
@@ -261,23 +218,25 @@ namespace Fig
return location;
}
Result<std::uint8_t, Error> CompileIdentiExpr(IdentiExpr *);
Result<std::uint8_t, Error> CompileLiteral(LiteralExpr *);
Result<std::uint8_t, Error> compileIdentiExpr(IdentiExpr *);
Result<std::uint8_t, Error> compileLiteral(LiteralExpr *);
Result<std::uint8_t, Error> CompileAssignment(
Result<std::uint8_t, Error> compileAssignment(
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 *); // 左值对象,可以是变量、结构体字段或模块对象
Result<std::uint8_t, Error> CompileExpr(Expr *);
Result<std::uint8_t, Error> compileExpr(Expr *);
/* Statements */
Result<void, Error> CompileVarDecl(VarDecl *);
Result<void, Error> CompileBlockStmt(BlockStmt *);
Result<void, Error> CompileIfStmt(IfStmt *);
Result<void, Error> CompileStmt(Stmt *);
Result<void, Error> compileVarDecl(VarDecl *);
Result<void, Error> compileBlockStmt(BlockStmt *);
Result<void, Error> compileIfStmt(IfStmt *);
Result<void, Error> compileWhileStmt(WhileStmt *);
Result<void, Error> compileStmt(Stmt *);
};
inline void DisassembleInstruction(Instruction inst, std::size_t index)

View File

@@ -9,18 +9,18 @@
namespace Fig
{
Result<std::uint8_t, Error> Compiler::CompileIdentiExpr(IdentiExpr *ie)
Result<std::uint8_t, Error> Compiler::compileIdentiExpr(IdentiExpr *ie)
{
// if (!HasLocal(ie->name))
// {
// return std::unexpected(Error(ErrorType::UseUndeclaredIdentifier,
// std::format("`{}` has not been defined", ie->name),
// "none",
// makeSourceLocation(ie)));
// }
return ResolveLocal(ie->name);
// TODO: 处理全局变量和闭包 Upvalue
std::uint8_t targetReg = current->fastRegMap[ie->localId];
if (targetReg == UINT8_MAX)
{
assert(false && "Compiler Bug: Encountered unmapped localId in fastRegMap!");
}
return targetReg;
}
Result<std::uint8_t, Error> Compiler::CompileLiteral(
Result<std::uint8_t, Error> Compiler::compileLiteral(
LiteralExpr *lit) // 编译字面量, 负责转换 token -> Value
{
const Token &token = lit->token;
@@ -47,8 +47,8 @@ namespace Fig
}
else if (token.type == TokenType::LiteralNumber)
{
// TODO: 更换为无异常手写数字解析版本
if (lexeme.contains(U'.'))
// TODO: 更换为无异常手写数字解析版本 (charconv也可)
if (lexeme.contains(U'.') || lexeme.contains(U'e'))
{
// 非整数
double d = std::stod(lexeme.toStdString());
@@ -63,23 +63,34 @@ namespace Fig
}
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);
Emit(Op::iABx(OpCode::LoadK, targetReg, kIndex));
return targetReg;
}
Result<std::uint8_t, Error> Compiler::CompileAssignment(
Result<std::uint8_t, Error> Compiler::compileAssignment(
InfixExpr *infix) // 编译赋值,由 CompileInfixExpr调用
{
// op必须为 =
const auto &_lhsReg = CompileLeftValue(infix->left); // 必须为左值对象
const auto &_lhsReg = compileLeftValue(infix->left); // 必须为左值对象
if (!_lhsReg)
{
return _lhsReg;
}
std::uint8_t lhsReg = *_lhsReg;
const auto &_rhsReg = CompileExpr(infix->right);
const auto &_rhsReg = compileExpr(infix->right);
std::uint8_t rhsReg = *_rhsReg;
FreeReg(rhsReg);
@@ -119,21 +130,21 @@ namespace Fig
}
return lhsReg; // 返回赋值的结果,支持连续赋值
}
Result<std::uint8_t, Error> Compiler::CompileInfixExpr(
Result<std::uint8_t, Error> Compiler::compileInfixExpr(
InfixExpr *infix) // 编译中缀表达式,返回一个存放结果的寄存器 ID
{
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)
{
return _lhsReg;
}
std::uint8_t lhsReg = *_lhsReg;
const auto &_rhsReg = CompileExpr(infix->right);
const auto &_rhsReg = compileExpr(infix->right);
if (!_rhsReg)
{
return _rhsReg;
@@ -171,25 +182,52 @@ namespace Fig
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");
}
return resultReg;
}
Result<std::uint8_t, Error> Compiler::CompileLeftValue(
Result<std::uint8_t, Error> Compiler::compileLeftValue(
Expr *expr) // 左值对象,可以是变量、结构体字段或模块对象
{
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:
return std::unexpected(Error(ErrorType::NotAnLvalue,
std::format("`{}` is not a lvalue, expect a valid lvalue", expr->toString()),
"none",
makeSourceLocation(expr)));
// Analyzer 有漏洞(编译器内部
// 直接崩溃
assert(false && "Compiler Bug: Invalid L-value bypassed Analyzer!");
return 0;
}
}
Result<std::uint8_t, Error> Compiler::CompileExpr(
Result<std::uint8_t, Error> Compiler::compileExpr(
Expr *expr) // 编译表达式,必定返回一个存放结果的寄存器 ID
{
switch (expr->type)
@@ -199,12 +237,12 @@ namespace Fig
case AstType::AstNode: assert(false && "CompileExpr: bad node type"); break;
case AstType::IdentiExpr: {
return CompileLeftValue(expr); // 左值直接转换成右值
return compileLeftValue(expr); // 左值直接转换成右值
}
case AstType::LiteralExpr: {
LiteralExpr *lit = static_cast<LiteralExpr *>(expr);
const auto &result = CompileLiteral(lit);
auto result = compileLiteral(lit);
if (!result)
{
return std::unexpected(result.error());
@@ -213,7 +251,7 @@ namespace Fig
return targetReg;
}
case AstType::InfixExpr: {
return CompileInfixExpr(static_cast<InfixExpr *>(expr));
return compileInfixExpr(static_cast<InfixExpr *>(expr));
}
}
}

View File

@@ -9,40 +9,40 @@
namespace Fig
{
Result<void, Error> Compiler::CompileVarDecl(VarDecl *varDecl)
Result<void, Error> Compiler::compileVarDecl(VarDecl *varDecl)
{
const String &name = varDecl->name;
// if (HasLocalInCurrentScope(name))
// {
// return std::unexpected(Error(ErrorType::RedeclarationError,
// std::format("variable `{}` has already defined in this scope", name),
// "change its name",
// makeSourceLocation(varDecl)));
// }
if (current->freeReg > MAX_LOCALS)
{
return std::unexpected(Error(ErrorType::TooManyLocals,
std::format("local limit exceeded: {}", MAX_LOCALS),
"try split function or use arrays/structs...",
makeSourceLocation(varDecl)));
}
std::uint8_t varReg;
if (varDecl->initExpr)
{
const auto &result = CompileExpr(varDecl->initExpr);
auto result = compileExpr(varDecl->initExpr);
if (!result)
{
return std::unexpected(result.error());
}
std::uint8_t resultReg = *result;
varReg = resultReg; // 复用临时计算结果寄存器
DeclareLocal(varDecl->isPublic, name, varReg);
varReg = DeclareLocal(varDecl->localId, resultReg); // 复用临时计算结果寄存器
}
else
{
varReg = DeclareLocal(varDecl->isPublic, name);
varReg = DeclareLocal(varDecl->localId);
}
return Result<void, Error>();
}
Result<void, Error> Compiler::CompileBlockStmt(BlockStmt *blockStmt)
Result<void, Error> Compiler::compileBlockStmt(BlockStmt *blockStmt)
{
for (Stmt *stmt : blockStmt->nodes)
{
const auto &result = CompileStmt(stmt);
auto result = compileStmt(stmt);
if (!result)
{
return result;
@@ -51,7 +51,7 @@ namespace Fig
return {};
}
Result<void, Error> Compiler::CompileIfStmt(IfStmt *stmt)
Result<void, Error> Compiler::compileIfStmt(IfStmt *stmt)
{
/*
if cond1
@@ -97,7 +97,7 @@ namespace Fig
*/
std::vector<int> exitJumps; // 所有分支都要跳到最后收集所有jump最后回填
const auto &condResult = CompileExpr(stmt->cond);
const auto &condResult = compileExpr(stmt->cond);
if (!condResult)
{
return std::unexpected(condResult.error());
@@ -106,7 +106,7 @@ namespace Fig
int jumpToNext = EmitJump(OpCode::JmpIfFalse, condReg);
FreeReg(condReg);
const auto &blockResult = CompileStmt(stmt->consequent);
const auto &blockResult = compileStmt(stmt->consequent);
if (!blockResult)
{
return blockResult;
@@ -117,7 +117,7 @@ namespace Fig
for (auto *elif : stmt->elifs)
{
const auto &elifCondResult = CompileExpr(elif->cond);
const auto &elifCondResult = compileExpr(elif->cond);
if (!elifCondResult)
return std::unexpected(elifCondResult.error());
std::uint8_t elifCondReg = *elifCondResult;
@@ -125,7 +125,7 @@ namespace Fig
jumpToNext = EmitJump(OpCode::JmpIfFalse, elifCondReg);
FreeReg(elifCondReg);
const auto &blockResult = CompileStmt(elif->consequent);
const auto &blockResult = compileStmt(elif->consequent);
if (!blockResult)
{
return blockResult;
@@ -136,7 +136,7 @@ namespace Fig
if (stmt->alternate)
{
const auto &result = CompileStmt(stmt->alternate);
auto result = compileStmt(stmt->alternate);
if (!result)
{
return result;
@@ -148,31 +148,65 @@ namespace Fig
}
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)
{
ExprStmt *exprStmt = static_cast<ExprStmt *>(stmt);
Expr *expr = exprStmt->expr;
const auto &result = CompileExpr(expr);
if (!result)
{
return std::unexpected(result.error());
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);
Expr *expr = exprStmt->expr;
auto result = compileExpr(expr);
if (!result)
{
return std::unexpected(result.error());
}
FreeReg(*result);
break;
}
case AstType::VarDecl: {
return compileVarDecl(static_cast<VarDecl *>(stmt));
}
case AstType::BlockStmt: {
return compileBlockStmt(static_cast<BlockStmt *>(stmt));
}
case AstType::IfStmt: {
return compileIfStmt(static_cast<IfStmt *>(stmt));
}
case AstType::WhileStmt: {
return compileWhileStmt(static_cast<WhileStmt *>(stmt));
}
FreeReg(*result);
}
else if (stmt->type == AstType::VarDecl)
{
return CompileVarDecl(static_cast<VarDecl *>(stmt));
}
else if (stmt->type == AstType::BlockStmt)
{
return CompileBlockStmt(static_cast<BlockStmt *>(stmt));
}
else if (stmt->type == AstType::IfStmt)
{
return CompileIfStmt(static_cast<IfStmt *>(stmt));
}
return Result<void, Error>();
}
}; // namespace Fig

View File

@@ -56,6 +56,9 @@ namespace Fig
case UseUndeclaredIdentifier: return "UseUndeclaredIdentifier";
case NotAnLvalue: return "NotAnLvalue";
case TypeError: return "TypeError";
case TooManyLocals: return "TooManyLocals";
case TooManyConstants: return "TooManyConstants";
// default: return "Some one forgot to add case to `ErrorTypeToString`";
}
}

View File

@@ -47,6 +47,10 @@ namespace Fig
UseUndeclaredIdentifier,
NotAnLvalue,
TypeError,
// compile errors
TooManyLocals,
TooManyConstants,
};
const char *ErrorTypeToString(ErrorType type);

View File

@@ -1,6 +1,7 @@
#include <Error/Error.hpp>
#include <Token/Token.hpp>
#include <Lexer/Lexer.hpp>
#include <Token/Token.hpp>
#include <iostream>
@@ -24,18 +25,18 @@ int main()
while (true)
{
const auto &result = lexer.NextToken();
auto result = lexer.NextToken();
if (!result.has_value())
{
ReportError(result.error(), manager);
break;
}
const Token &token = *result;
const Token &token = *result;
const String &lexeme = manager.GetSub(token.index, token.length);
const auto &type = magic_enum::enum_name(token.type);
const auto &type = magic_enum::enum_name(token.type);
if (token.type == TokenType::EndOfFile)
{
std::cout << "EOF: " << type << " at " << token.index << '\n';
std::cout << "EOF: " << type << " at " << token.index << '\n';
break;
}
std::cout << lexeme << " --> " << type << '\n';

View File

@@ -11,14 +11,16 @@ namespace Fig
{
Result<LiteralExpr *, Error> Parser::parseLiteralExpr() // 当前token为literal时调用
{
state = State::ParsingLiteralExpr;
StateProtector p(this, {State::ParsingLiteralExpr});
const Token &literal_token = consumeToken();
LiteralExpr *node = new LiteralExpr(literal_token, makeSourceLocation(literal_token));
return node;
}
Result<IdentiExpr *, Error> Parser::parseIdentiExpr() // 当前token为Identifier调用
{
state = State::ParsingIdentiExpr;
StateProtector p(this, {State::ParsingIdentiExpr});
const Token &identifier = consumeToken();
IdentiExpr *node = new IdentiExpr(
srcManager.GetSub(identifier.index, identifier.length), makeSourceLocation(identifier));
@@ -27,7 +29,8 @@ namespace Fig
Result<InfixExpr *, Error> Parser::parseInfixExpr(Expr *lhs) // 当前token为 op
{
state = State::ParsingInfixExpr;
StateProtector p(this, {State::ParsingInfixExpr});
const Token &op_token = consumeToken();
BinaryOperator op = TokenToBinaryOp(op_token);
BindingPower rbp = GetBinaryOpRBp(op);
@@ -45,7 +48,8 @@ namespace Fig
Result<PrefixExpr *, Error> Parser::parsePrefixExpr() // 当前token为op
{
state = State::ParsingPrefixExpr;
StateProtector p(this, {State::ParsingPrefixExpr});
const Token &op_token = consumeToken();
UnaryOperator op = TokenToUnaryOp(op_token);
@@ -64,7 +68,8 @@ namespace Fig
Result<IndexExpr *, Error> Parser::parseIndexExpr(
Expr *base) // 由 parseExpression调用, 当前token为 `[`
{
state = State::ParsingIndexExpr;
StateProtector p(this, {State::ParsingIndexExpr});
const Token &lbracket_token = consumeToken(); // consume `[`
const auto &index_result = parseExpression();
@@ -89,7 +94,8 @@ namespace Fig
Result<CallExpr *, Error> Parser::parseCallExpr(
Expr *callee) // 由 parseExpression调用, 当前token为 `(`
{
state = State::ParsingCallExpr;
StateProtector p(this, {State::ParsingCallExpr});
const Token &lparen_token = consumeToken(); // consume `(`
FnCallArgs callArgs;
@@ -137,52 +143,8 @@ namespace Fig
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;
Token token = currentToken();
@@ -191,7 +153,6 @@ namespace Fig
const auto &lhs_result = parseIdentiExpr();
if (!lhs_result)
{
resetTermintors();
return std::unexpected(lhs_result.error());
}
lhs = *lhs_result;
@@ -201,7 +162,6 @@ namespace Fig
const auto &lhs_result = parseLiteralExpr();
if (!lhs_result)
{
resetTermintors();
return std::unexpected(lhs_result.error());
}
lhs = *lhs_result;
@@ -211,7 +171,6 @@ namespace Fig
const auto &lhs_result = parsePrefixExpr();
if (!lhs_result)
{
resetTermintors();
return std::unexpected(lhs_result.error());
}
lhs = *lhs_result;
@@ -222,7 +181,6 @@ namespace Fig
const auto &expr_result = parseExpression(0);
if (!expr_result)
{
resetTermintors();
return expr_result;
}
const Token &rparen_token = consumeToken(); // consume `)`
@@ -238,7 +196,6 @@ namespace Fig
if (!lhs)
{
resetTermintors();
return std::unexpected(Error(ErrorType::ExpectedExpression,
"expected expression",
"insert expressions",
@@ -252,10 +209,6 @@ namespace Fig
{
break;
}
if (token.type == stop || token.type == stop2)
{
break;
}
if (IsTokenOp(token.type /* isBinary = true */)) // 是否为二元运算符
{
@@ -268,7 +221,7 @@ namespace Fig
break;
}
const auto &result = parseInfixExpr(lhs);
auto result = parseInfixExpr(lhs);
if (!result)
{
resetTermintors();

View File

@@ -5,7 +5,6 @@
@date 2026-02-14
*/
#include <Parser/Parser.hpp>
namespace Fig
@@ -15,7 +14,7 @@ namespace Fig
Program *program = new Program;
while (!isEOF)
{
const auto &result = parseStatement();
auto result = parseStatement();
if (!result)
{
return std::unexpected(result.error());
@@ -29,4 +28,4 @@ namespace Fig
}
return program;
}
};
}; // namespace Fig

View File

@@ -41,7 +41,7 @@ namespace Fig
{
return buffer[++index];
}
const auto &result = lexer.NextToken();
auto result = lexer.NextToken();
if (!result)
{
ReportError(result.error(), srcManager);
@@ -82,7 +82,7 @@ namespace Fig
size_t peekIndex = index + lookahead;
while (peekIndex >= buffer.size() && !isEOF)
{
const auto &result = lexer.NextToken();
auto result = lexer.NextToken();
if (!result)
{
ReportError(result.error(), srcManager);
@@ -121,51 +121,146 @@ namespace Fig
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(
ErrorType::SyntaxError,
std::format("expect '{}' in {}, got `{}`", expect, stmtType, magic_enum::enum_name(tokenGot.type)),
return Error(ErrorType::SyntaxError,
std::format("expect '{}' in {}, got `{}`",
expect,
stmtType,
magic_enum::enum_name(tokenGot.type)),
"none",
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(
ErrorType::SyntaxError,
return Error(ErrorType::SyntaxError,
"expect ';' after statement",
"insert ';'",
makeSourceLocation(currentToken()),
loc
);
loc);
}
public:
enum class State : std::uint8_t
struct State
{
Standby,
enum StateType : std::uint8_t
{
Standby,
ParsingLiteralExpr,
ParsingIdentiExpr,
ParsingLiteralExpr,
ParsingIdentiExpr,
ParsingInfixExpr,
ParsingPrefixExpr,
ParsingInfixExpr,
ParsingPrefixExpr,
ParsingIndexExpr,
ParsingCallExpr,
ParsingIndexExpr,
ParsingCallExpr,
ParsingVarDecl,
ParsingIf,
ParsingVarDecl,
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 &currentState()
{
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) :
lexer(_lexer), srcManager(_srcManager), fileName(std::move(_fileName))
{
state = State::Standby;
pushState(State());
}
private:
@@ -175,33 +270,33 @@ namespace Fig
return SourceLocation(SourcePosition(line, column, tok.length),
fileName,
"[internal parser]",
magic_enum::enum_name(state).data());
magic_enum::enum_name(currentState().type).data());
}
/* Expressions */
Result<LiteralExpr *, Error> parseLiteralExpr(); // 当前token为literal时调用
Result<IdentiExpr *, Error> parseIdentiExpr(); // 当前token为Identifier调用
Result<InfixExpr *, Error> parseInfixExpr(Expr *); // 由 parseExpression递归调用, 当前token为op
Result<PrefixExpr *, Error> parsePrefixExpr(); // 由 parseExpression递归调用, 当前token为op
Result<InfixExpr *, Error> parseInfixExpr(
Expr *); // 由 parseExpression递归调用, 当前token为op
Result<PrefixExpr *, Error> parsePrefixExpr(); // 由 parseExpression递归调用, 当前token为op
Result<IndexExpr *, Error> parseIndexExpr(Expr *); // 由 parseExpression调用, 当前token为 `[`
Result<CallExpr *, Error> parseCallExpr(Expr *); // 由 parseExpression调用, 当前token为 `(`
Result<IndexExpr *, Error> parseIndexExpr(
Expr *); // 由 parseExpression调用, 当前token为 `[`
Result<CallExpr *, Error> parseCallExpr(Expr *); // 由 parseExpression调用, 当前token为 `(`
const std::unordered_set<TokenType> &getBaseTerminators();
std::unordered_set<TokenType> &getTerminators(); // 返回固定的终止符
void resetTermintors();
bool shouldTerminate(); // 判断是否终结
Result<Expr *, Error> parseExpression(BindingPower = 0, TokenType stop = TokenType::Semicolon, TokenType stop2 = TokenType::Semicolon);
Result<Expr *, Error> parseExpression(BindingPower = 0);
/* Statements */
Result<BlockStmt *, Error> parseBlockStmt(); // 当前token为 {
Result<VarDecl *, Error> parseVarDecl(bool); // 由 parseStatement调用, 当前token为 var
Result<IfStmt *, Error> parseIfStmt(); // 由 parseStatement调用, 当前token is if
Result<Stmt *, Error> parseStatement();
Result<BlockStmt *, Error> parseBlockStmt(); // 当前token为 {
Result<VarDecl *, Error> parseVarDecl(bool); // 由 parseStatement调用, 当前token为 var
Result<IfStmt *, Error> parseIfStmt(); // 由 parseStatement调用, 当前token if
Result<WhileStmt *, Error> parseWhileStmt(); // 由 parseStatement调用, 当前token为 while
Result<Stmt *, Error> parseStatement();
public:
Result<Program *, Error> Parse();
};
#define SET_STOP_AT(...) currentState().stopAt = {__VA_ARGS__};
}; // namespace Fig

View File

@@ -16,9 +16,9 @@ int main()
return 1;
}
Lexer lexer(source, fileName);
Lexer lexer(source, fileName);
Parser parser(lexer, srcManager, fileName);
const auto &result = parser.Parse();
auto result = parser.Parse();
if (!result)
{
ReportError(result.error(), srcManager);

View File

@@ -19,14 +19,14 @@ namespace Fig
{
return std::unexpected(Error(ErrorType::SyntaxError,
"unclosed braces in block stmt",
"insert `}`",
"insert '}'",
location));
}
if (match(TokenType::RightBrace))
{
break;
}
const auto &result = parseStatement();
auto result = parseStatement();
if (!result)
{
return std::unexpected(result.error());
@@ -38,7 +38,7 @@ namespace Fig
Result<VarDecl *, Error> Parser::parseVarDecl(
bool isPublic) // 由 parseStatement调用, 当前token为 var
{
state = State::ParsingVarDecl;
StateProtector p(this, {State::ParsingVarDecl});
SourceLocation location = makeSourceLocation(consumeToken()); // consume `var`
@@ -52,7 +52,8 @@ namespace Fig
Expr *typeSpeicifer = nullptr;
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)
{
return std::unexpected(result.error());
@@ -61,10 +62,10 @@ namespace Fig
}
Expr *initExpr = nullptr;
bool isInfer = false;
bool isInfer = false;
if (match(TokenType::Assign))
{
const auto &result = parseExpression();
auto result = parseExpression();
if (!result)
{
return std::unexpected(result.error());
@@ -73,22 +74,21 @@ namespace Fig
}
else if (match(TokenType::Walrus)) // :=
{
if (typeSpeicifer) // 指定了类型同时使用 :=
if (typeSpeicifer) // 指定了类型同时使用 :=
{
return std::unexpected(Error(
ErrorType::SyntaxError,
return std::unexpected(Error(ErrorType::SyntaxError,
"used type infer but specifying the type",
"change `:=` to '='",
makeSourceLocation(prevToken()) // :=
));
));
}
const auto &result = parseExpression();
auto result = parseExpression();
if (!result)
{
return std::unexpected(result.error());
}
initExpr = *result;
isInfer = true; // 使用类型自动推断 :=
isInfer = true; // 使用类型自动推断 :=
}
if (!match(TokenType::Semicolon))
{
@@ -100,14 +100,16 @@ namespace Fig
Result<IfStmt *, Error> Parser::parseIfStmt() // 由 parseStatement调用, 当前token is if
{
state = State::ParsingIf;
StateProtector p(this, {State::ParsingIf});
SourceLocation location = makeSourceLocation(consumeToken()); // consume `if`
Expr *cond = nullptr;
if (match(TokenType::LeftParen)) // match and consume `(`
{
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)
{
return std::unexpected(result.error());
@@ -124,21 +126,21 @@ namespace Fig
}
else
{
const auto &result = parseExpression(0, TokenType::LeftBrace);
SET_STOP_AT(TokenType::LeftBrace);
auto result = parseExpression(0);
if (!result)
{
return std::unexpected(result.error());
}
cond = *result;
}
state = State::ParsingIf;
if (currentToken().type != TokenType::LeftBrace)
{
return std::unexpected(
makeUnexpectTokenError("IfStmt", "LeftBrace `{`", currentToken()));
}
const auto &result = parseBlockStmt();
auto result = parseBlockStmt();
if (!result)
{
return std::unexpected(result.error());
@@ -167,13 +169,13 @@ namespace Fig
if (match(TokenType::LeftParen)) // `(`
{
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)
{
return std::unexpected(result.error());
}
state = State::ParsingIf;
if (!match(TokenType::RightParen))
{
delete *result;
@@ -186,25 +188,24 @@ namespace Fig
}
else
{
const auto &result = parseExpression(0, TokenType::LeftBrace);
SET_STOP_AT(TokenType::LeftBrace);
auto result = parseExpression(0);
if (!result)
{
return std::unexpected(result.error());
}
state = State::ParsingIf;
cond = *result;
cond = *result;
}
if (currentToken().type != TokenType::LeftBrace)
{
return std::unexpected(
makeUnexpectTokenError("ElseIfStmt", "LeftBrace `{`", currentToken()));
}
const auto &result = parseBlockStmt();
auto result = parseBlockStmt();
if (!result)
{
return std::unexpected(result.error());
}
state = State::ParsingIf;
BlockStmt *consequent = *result;
ElseIfStmt *elif = new ElseIfStmt(cond, consequent, elseLocation);
elifs.push_back(elif);
@@ -224,12 +225,11 @@ namespace Fig
return std::unexpected(
makeUnexpectTokenError("ElseStmt", "LeftBrace `{`", currentToken()));
}
const auto &result = parseBlockStmt();
auto result = parseBlockStmt();
if (!result)
{
return std::unexpected(result.error());
}
state = State::ParsingIf;
alternate = *result;
}
}
@@ -237,9 +237,68 @@ namespace Fig
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()
{
state = State::Standby;
StateProtector p(this, {State::Standby});
if (currentToken().type == TokenType::Public)
{
consumeToken(); // consume `public`
@@ -247,20 +306,38 @@ namespace Fig
{
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)
{
return parseVarDecl(false);
}
if (currentToken().type == TokenType::If)
{
return parseIfStmt();
}
if (currentToken().type == TokenType::While)
{
return parseWhileStmt();
}
if (isEOF)
{
return nullptr;
}
const auto &expr_result = parseExpression();
if (!expr_result)
{

View File

@@ -11,7 +11,8 @@ namespace Fig
{
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,
std::format("variable `{}` has already defined in this scope", stmt->name),
@@ -50,7 +51,7 @@ namespace Fig
"none",
makeSourceLocation(stmt->initExpr)));
}
env.Define(stmt->name, declaredType, stmt->isPublic, false);
stmt->localId = env.Define(stmt->name, declaredType, stmt->isPublic, false);
return {};
}
@@ -63,12 +64,11 @@ namespace Fig
}
if (stmt->cond->resolvedType != TypeTag::Any && stmt->cond->resolvedType != TypeTag::Bool)
{
return std::unexpected(Error(
ErrorType::TypeError,
std::format("if condition must be boolean, got `{}`", magic_enum::enum_name(stmt->cond->resolvedType)),
return std::unexpected(Error(ErrorType::TypeError,
std::format("if condition must be boolean, got `{}`",
magic_enum::enum_name(stmt->cond->resolvedType)),
"ensure condition is boolean",
makeSourceLocation(stmt->cond)
));
makeSourceLocation(stmt->cond)));
}
auto consequentRes = analyzeStmt(stmt->consequent);
if (!consequentRes)
@@ -106,6 +106,31 @@ namespace Fig
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)
{
auto sym = env.Resolve(expr->name);
@@ -117,8 +142,11 @@ namespace Fig
makeSourceLocation(expr)));
}
// TODO: 引入 Module 跨文件 import检查 isPublic
expr->resolvedType = sym->type;
expr->localId = sym->localId;
expr->resolvedType = sym->type;
expr->resolvedDepth = sym->depth;
expr->isGlobal = (sym->depth == 0);
return {};
}
@@ -138,7 +166,7 @@ namespace Fig
switch (expr->op)
{
// 1. 算术族 (+, -, *, /, **)
// 算术族 (+, -, *, /, **)
case BinaryOperator::Add:
if (lType == TypeTag::String && rType == TypeTag::String)
{
@@ -172,7 +200,7 @@ namespace Fig
}
break;
// 2. 整数特化族 (%, &, |, ^, <<, >>)
// 整数特化族 (%, &, |, ^, <<, >>)
case BinaryOperator::Modulo:
case BinaryOperator::BitAnd:
case BinaryOperator::BitOr:
@@ -196,8 +224,7 @@ namespace Fig
}
break;
// 3. 比较族 (==, !=, <, >, <=, >=)
// 比较族 (==, !=, <, >, <=, >=)
case BinaryOperator::Equal:
case BinaryOperator::NotEqual:
@@ -206,7 +233,8 @@ namespace Fig
case BinaryOperator::LessEqual:
case BinaryOperator::GreaterEqual:
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)
|| (lType == TypeTag::Double && rType == TypeTag::Int)))
@@ -217,7 +245,7 @@ namespace Fig
makeSourceLocation(expr)));
}
}
// TODO: 支持Struct后进行检查右操作数是 Struct才合理
// 如 1.2 is Int --> false
// 1 is Int --> true
@@ -225,8 +253,7 @@ namespace Fig
expr->resolvedType = TypeTag::Bool;
break;
// 4. 逻辑族 (&&, ||)
// 逻辑族 (&&, ||)
case BinaryOperator::LogicalAnd:
case BinaryOperator::LogicalOr:
if (lType == TypeTag::Bool && rType == TypeTag::Bool)
@@ -246,8 +273,7 @@ namespace Fig
}
break;
// 5. 纯赋值与复合赋值族 (=, +=, -=, ...)
// 纯赋值与复合赋值族 (=, +=, -=, ...)
case BinaryOperator::Assign:
case BinaryOperator::AddAssign:
case BinaryOperator::SubAssign:
@@ -258,12 +284,11 @@ namespace Fig
// 左侧必须是合法的 L-Value
if (!isValidLvalue(expr->left))
{
return std::unexpected(
Error(ErrorType::NotAnLvalue,
"invalid assignment target",
"left side must be a variable, property, or indexable target",
makeSourceLocation(expr->left) // 错误精准定位到左侧节点
));
return std::unexpected(Error(ErrorType::NotAnLvalue,
"invalid assignment target",
"left side must be a variable, property, or indexable target",
makeSourceLocation(expr->left) // 错误精准定位到左侧节点
));
}
// 类型匹配拦截 (纯赋值)
@@ -283,8 +308,7 @@ namespace Fig
expr->resolvedType = lType;
break;
// 6. 成员访问 (.)
// 成员访问 (.)
case BinaryOperator::MemberAccess:
if (lType != TypeTag::Struct && lType != TypeTag::Any)
{
@@ -293,6 +317,15 @@ namespace Fig
"check if the left side evaluates to an object",
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;
break;
@@ -335,14 +368,18 @@ namespace Fig
case AstType::IfStmt: {
return analyzeIfStmt(static_cast<IfStmt *>(stmt));
}
// TODO: 其他语句分析
// default:
// return std::unexpected(Error(ErrorType::TypeError,
// "unsupported statement type in analyzer",
// "internal compiler error",
// makeSourceLocation(stmt)));
case AstType::WhileStmt: {
return analyzeWhileStmt(static_cast<WhileStmt *>(stmt));
}
// TODO: 其他语句分析
// default:
// return std::unexpected(Error(ErrorType::TypeError,
// "unsupported statement type in analyzer",
// "internal compiler error",
// makeSourceLocation(stmt)));
}
return {};
}
@@ -356,17 +393,13 @@ namespace Fig
{
case AstType::LiteralExpr: {
auto *lit = static_cast<LiteralExpr *>(expr);
switch(lit->token.type)
switch (lit->token.type)
{
case TokenType::LiteralTrue:
case TokenType::LiteralFalse:
lit->resolvedType = TypeTag::Bool;
break;
case TokenType::LiteralNull:
lit->resolvedType = TypeTag::Null;
break;
case TokenType::LiteralFalse: lit->resolvedType = TypeTag::Bool; break;
case TokenType::LiteralNull: lit->resolvedType = TypeTag::Null; break;
case TokenType::LiteralNumber: {
const String &lexeme = manager.GetSub(lit->token.index, lit->token.length);
if (lexeme.contains(U'.') || lexeme.contains(U'e'))
@@ -385,9 +418,10 @@ namespace Fig
break;
}
default:
default: {
lit->resolvedType = TypeTag::Any;
break;
}
}
return {};
}

View File

@@ -56,6 +56,7 @@ namespace Fig
Result<void, Error> analyzeVarDecl(VarDecl *);
Result<void, Error> analyzeIfStmt(IfStmt *);
Result<void, Error> analyzeWhileStmt(WhileStmt *);
Result<void, Error> analyzeIdentiExpr(IdentiExpr *);
Result<void, Error> analyzeInfixExpr(InfixExpr *);

View File

@@ -24,10 +24,10 @@ int main()
return 1;
}
Lexer lexer(manager.GetSource(), fileName);
Lexer lexer(manager.GetSource(), fileName);
Parser parser(lexer, manager, fileName);
const auto &result = parser.Parse();
auto result = parser.Parse();
if (!result)
{
ReportError(result.error(), manager);

View File

@@ -7,15 +7,15 @@
#pragma once
#include <Sema/Type.hpp>
#include <Deps/Deps.hpp>
#include <Error/Error.hpp>
#include <Sema/Type.hpp>
#include <cassert>
#include <optional>
namespace Fig
{
// 记录在 Analyzer 中的符号元数据
struct Symbol
{
@@ -24,41 +24,108 @@ namespace Fig
bool isPublic;
int depth; // 词法作用域深度
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
{
private:
DynArray<Symbol> symbols;
int currentDepth = 0;
SemaFuncState *current = nullptr;
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()
{
currentDepth++;
current->currentDepth++;
current->scopeStack.push_back({symbols.size(), current->nextLocalId});
}
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();
}
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)
{
if (it->depth < currentDepth)
if (it->depth < current->currentDepth)
break;
if (it->name == name)
{
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
@@ -74,7 +141,7 @@ namespace Fig
int GetDepth() const
{
return currentDepth;
return current->currentDepth;
}
};
} // namespace Fig

View File

@@ -3,13 +3,15 @@
#include <Deps/Deps.hpp>
#include <Lexer/Lexer.hpp>
#include <Parser/Parser.hpp>
#include <SourceManager/SourceManager.hpp>
#include <Sema/Analyzer.hpp>
#include <SourceManager/SourceManager.hpp>
#include <VM/VM.hpp>
#include <chrono>
#include <iostream>
#include <print>
#include <chrono>
int main()
{
@@ -38,7 +40,7 @@ int main()
}
Program *program = *program_result;
Analyzer analyzer(manager);
Analyzer analyzer(manager);
const auto &analyzeResult = analyzer.Analyze(program);
if (!analyzeResult)
{
@@ -47,7 +49,6 @@ int main()
}
std::cout << "analyzer: Program OK, PASSED\n";
Compiler compiler(fileName, manager);
const auto &proto_result = compiler.Compile(program);
if (!proto_result)
@@ -67,10 +68,10 @@ int main()
DumpCode(proto->code);
std::cout << "\nMax Stack Size: " << (int) proto->maxStack << std::endl;
VM vm;
const auto &result_ = vm.Execute(proto);
auto result_ = vm.Execute(proto);
if (!result_)
{
ReportError(result_.error(), manager);