重构语法树/符号表

This commit is contained in:
csh
2025-10-15 20:31:00 +08:00
parent f52768e385
commit 1f7045140e
113 changed files with 229450 additions and 221041 deletions
+541
View File
@@ -0,0 +1,541 @@
# 从反序列化到符号表 - 设计架构
## 📐 系统架构总览
```
┌─────────────────────────────────────────────────────────────────┐
│ Source Code │
│ (tsl) │
└────────────────────────┬────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Tree-sitter Parser │
│ (外部依赖,生成 TSTree) │
└────────────────────────┬────────────────────────────────────────┘
┌────────┐
│ TSTree │ Parse Tree (CST)
│ TSNode │
└────┬───┘
┌─────────────────────────────────────────────────────────────────┐
│ AST 反序列化层 (ast/) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ deserializer.hpp/cpp │ │
│ │ - ParseRoot() │ │
│ │ - ParseNode() │ │
│ │ - ParseVarDeclaration(), ParseFunctionDefinition()... │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ types.hpp │ │
│ │ - ASTNode (variant) │ │
│ │ - VarDeclaration, FunctionDefinition, ClassDefinition │ │
│ │ - Expression, Block, Signature, Parameter... │ │
│ └─────────────────────────────────────────────────────────┘ │
└────────────────────────┬────────────────────────────────────────┘
┌────────────────────┐
│ vector<ASTNode> │ 抽象语法树
│ ParseResult │
└──────┬─────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 符号表构建层 (symbol/) │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Phase 1: Collection (builder/collector.hpp/cpp) │ │
│ │ - 遍历 AST │ │
│ │ - 创建符号 (Variable, Function, Class...) │ │
│ │ - 插入符号表 │ │
│ │ - 建立作用域层次 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Phase 2: Resolution (builder/resolver.hpp/cpp) │ │
│ │ - 解析 Unit 依赖关系 │ │
│ │ - 解析类继承关系 │ │
│ │ - 检测循环依赖 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Phase 3: Validation (builder/validator.hpp/cpp) │ │
│ │ - 验证类型引用 │ │
│ │ - 验证方法覆盖 │ │
│ │ - 验证访问权限 │ │
│ │ - 验证虚方法 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Coordinator (builder/builder.hpp/cpp) │ │
│ │ - 协调三阶段流程 │ │
│ │ - 错误收集和报告 │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────┬────────────────────────────────────────┘
┌────────────────────┐
│ SymbolRegistry │ 完整的符号表
│ - GlobalScope │
│ - Units │
└──────┬─────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 应用层 │
│ - LSP 服务 (代码补全、跳转定义、查找引用...) │
│ - 语义分析 │
│ - 代码生成 │
└─────────────────────────────────────────────────────────────────┘
```
---
## 🔄 数据流详解
### 1. 解析阶段 (Tree-sitter → AST)
```
Source Code
├─→ Tree-sitter Parser
│ │
│ └─→ TSTree (Concrete Syntax Tree)
│ │
│ └─→ TSNode (每个语法节点)
└─→ AST Deserializer
├─→ ParseRoot(TSNode, source)
│ │
│ └─→ ParseNode() 递归解析
│ │
│ ├─→ ParseVarDeclaration()
│ ├─→ ParseFunctionDefinition()
│ ├─→ ParseClassDefinition()
│ └─→ ...
└─→ vector<ASTNode>
└─→ AST (抽象语法树)
```
**关键点**
- Tree-sitter 生成 CST(具体语法树),包含所有语法细节
- Deserializer 将 CST 转换为 AST(抽象语法树),去除语法细节
- AST 使用 `std::variant<...>` 表示不同类型的节点
### 2. 符号表构建阶段 (AST → Symbol Table)
```
vector<ASTNode>
├─→ Phase 1: Collection
│ │
│ ├─→ 遍历每个 ASTNode
│ │ │
│ │ ├─→ Visit(UnitDefinition)
│ │ │ └─→ CreateUnit → AddUnit
│ │ │
│ │ ├─→ Visit(ClassDefinition)
│ │ │ └─→ CreateClass → Insert
│ │ │ │
│ │ │ └─→ Visit(ClassMembers)
│ │ │
│ │ ├─→ Visit(FunctionDefinition)
│ │ │ └─→ CreateFunction → InsertFunction
│ │ │ │
│ │ │ └─→ CollectFunctionBody
│ │ │
│ │ └─→ Visit(VarDeclaration)
│ │ └─→ CreateVariable → Insert
│ │
│ └─→ 结果:带有符号但引用未解析的符号表
├─→ Phase 2: Resolution
│ │
│ ├─→ ResolveUnitDependencies()
│ │ │
│ │ └─→ 对每个 Unit.uses 查找目标 Unit
│ │ └─→ 检测循环依赖
│ │
│ └─→ ResolveClassHierarchy()
│ │
│ └─→ 对每个 Class.parent_names 查找父类
│ └─→ 检测循环继承
└─→ Phase 3: Validation
├─→ ValidateTypeReferences()
│ └─→ 检查所有类型名是否存在
├─→ ValidateMethodOverrides()
│ └─→ 检查 override 是否合法
└─→ ValidateVirtualMethods()
└─→ 检查虚方法表一致性
```
---
## 🏗️ 模块职责划分
### 📦 AST 模块 (ast/)
| 组件 | 职责 | 输入 | 输出 |
|------|------|------|------|
| **deserializer** | 将 Tree-sitter 的 CST 转换为 AST | TSNode, source code | vector<ASTNode> |
| **types** | 定义 AST 节点类型 | - | 类型定义 |
**设计原则**
- 无状态转换(纯函数)
- 错误容忍(收集错误而非中断)
- 完整信息保留(位置、类型、文本)
---
### 📦 符号表模块 (symbol/)
#### 🔹 core/ - 核心类型
| 文件 | 职责 | 关键类型 |
|------|------|---------|
| **error** | 定义错误类型 | ErrorKind, Error |
| **symbol** | 定义所有符号类型 | Symbol, Variable, Function, Class... |
| **table** | 管理作用域和符号 | Table, LookupResult |
| **registry** | 管理全局资源 | SymbolRegistry |
#### 🔹 builder/ - 构建流程
| 文件 | 职责 | 主要方法 |
|------|------|---------|
| **reporter** | 收集和报告错误 | Report(), GetErrors() |
| **collector** | 阶段1: 收集符号 | Collect(), Visit() |
| **resolver** | 阶段2: 解析引用 | Resolve(), ResolveUnitDependencies() |
| **validator** | 阶段3: 验证完整性 | Validate(), ValidateTypeReferences() |
| **builder** | 协调三阶段流程 | Build() |
#### 🔹 factory/ - 工厂和管理
| 文件 | 职责 | 主要功能 |
|------|------|---------|
| **factory** | 创建符号实例 | CreateVariable(), CreateClass()... |
| **scope_manager** | 管理当前作用域 | EnterScope(), ScopeGuard (RAII) |
#### 🔹 utils/ - 工具类
| 文件 | 职责 | 主要功能 |
|------|------|---------|
| **type** | 类型操作工具 | TypeFactory, TypeQuery, TypeFormatter |
| **signature** | 签名操作工具 | SignatureComparator, SignatureFormatter |
| **class_member** | 成员查找 | FindMember(), GetAllMethods() |
| **class_hierarchy** | 层次分析 | BuildVTable(), ValidateHierarchy() |
---
## 🔗 模块间依赖关系
```
┌─────────────────────────────────────────────────────────┐
│ Application │
└──────────────────────┬──────────────────────────────────┘
│ uses
┌─────────────────────────────────────────────────────────┐
│ symbol/builder/builder │
│ (SymbolTableBuilder) │
└───────┬──────────────────────────────────┬──────────────┘
│ uses │ uses
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ symbol/builder/ │ │ symbol/core/ │
│ - collector │◄─────────────│ - registry │
│ - resolver │ uses │ - table │
│ - validator │ │ - symbol │
│ - reporter │ │ - error │
└────────┬─────────┘ └────────┬─────────┘
│ uses │
▼ │
┌──────────────────┐ │
│ symbol/factory/ │◄──────────────────────┘
│ - factory │ uses
│ - scope_manager │
└────────┬─────────┘
│ uses
┌──────────────────┐
│ symbol/utils/ │
│ - type │
│ - signature │
│ - class_member │
│ - class_hierarchy│
└──────────────────┘
```
**依赖规则**
- 上层模块依赖下层模块
- builder 依赖 core, factory, utils
- factory 依赖 core, utils
- utils 依赖 core
- core 无外部依赖(除了 ast)
---
## 🎯 关键设计模式
### 1. Visitor 模式 (AST 遍历)
```cpp
// Collector 访问 AST
class Collector {
bool Visit(const ast::ASTNode& node) {
if (auto* unit = std::get_if<ast::UnitDefinition>(&node))
return CollectUnit(*unit);
if (auto* cls = std::get_if<ast::ClassDefinition>(&node))
return CollectClass(*cls);
// ...
}
};
```
**优点**
- 分离数据结构和操作
- 易于添加新的访问操作
- 类型安全(使用 variant
### 2. Factory 模式 (符号创建)
```cpp
// 统一的符号创建入口
class Factory {
static VariablePtr CreateVariable(...);
static FunctionPtr CreateFunction(...);
static ClassPtr CreateClass(...);
};
```
**优点**
- 统一创建逻辑
- 易于维护和扩展
- 可以添加缓存、验证等逻辑
### 3. RAII 模式 (作用域管理)
```cpp
// 自动管理作用域切换
class ScopeGuard {
~ScopeGuard() { /* 自动恢复 */ }
};
// 使用
auto guard = scope_manager.EnterScope(new_scope);
// 作用域内操作
// guard 析构时自动恢复
```
**优点**
- 异常安全
- 自动资源管理
- 避免忘记恢复
### 4. Builder 模式 (符号表构建)
```cpp
class SymbolTableBuilder {
bool Build(nodes) {
Collector collector(...);
collector.Collect(nodes);
ReferenceResolver resolver(...);
resolver.Resolve();
Validator validator(...);
validator.Validate();
}
};
```
**优点**
- 分步构建复杂对象
- 易于理解和维护
- 可以中断和恢复
### 5. Strategy 模式 (错误报告)
```cpp
class ErrorReporter {
void Report(ErrorKind kind, ...);
};
// 不同组件使用同一报告器
Collector collector(registry, reporter);
Resolver resolver(registry, reporter);
Validator validator(registry, reporter);
```
**优点**
- 统一错误处理
- 易于替换报告策略
- 集中管理错误
---
## 📊 性能考虑
### 1. 时间复杂度
| 阶段 | 复杂度 | 说明 |
|------|--------|------|
| **解析** | O(n) | n = 源代码大小 |
| **收集** | O(m) | m = AST 节点数 |
| **解析引用** | O(u + c) | u = Unit数, c = Class数 |
| **验证** | O(s) | s = 符号总数 |
**总体**O(n + m + s) ≈ O(n),线性时间
### 2. 空间复杂度
| 数据结构 | 空间 | 优化 |
|---------|------|------|
| **AST** | O(m) | 构建符号表后可释放 |
| **符号表** | O(s) | 使用智能指针共享 |
| **作用域树** | O(d) | d = 作用域深度,通常很小 |
**总体**O(n),线性空间
### 3. 优化技术
- **增量更新**:只重新解析修改的文件
- **缓存**:缓存符号查找结果
- **延迟加载**:按需加载 Unit 内容
- **并行处理**:独立 Unit 可并行构建
---
## 🛡️ 错误处理策略
### 错误分类
| 错误类型 | 严重性 | 处理 |
|---------|--------|------|
| **语法错误** | Fatal | Tree-sitter 处理 |
| **结构错误** | Error | 收集但继续 |
| **类型错误** | Error | 收集但继续 |
| **警告** | Warning | 记录不中断 |
### 错误恢复
```
错误发生
├─→ 记录错误信息(位置、消息)
├─→ 尝试继续处理
│ └─→ 跳过当前节点
│ 或使用默认值
└─→ 返回 false 或 Error
└─→ 上层决定是否继续
```
**原则**
- 尽可能收集多个错误
- 不因一个错误而停止整个过程
- 提供详细的错误位置和上下文
---
## 🔍 使用示例
### 完整流程
```cpp
#include "ast/deserializer.hpp"
#include "symbol/builder/builder.hpp"
int main() {
// 1. 解析源代码
std::string source = ReadFile("program.pas");
TSTree* tree = ts_parser_parse_string(parser, nullptr,
source.c_str(),
source.length());
TSNode root = ts_tree_root_node(tree);
// 2. 反序列化为 AST
auto parse_result = ast::deserializer::ParseRoot(root, source);
if (parse_result.HasErrors()) {
// 处理解析错误
for (const auto& error : parse_result.errors) {
std::cerr << error.message << std::endl;
}
}
// 3. 构建符号表
symbol::SymbolTableBuilder builder;
bool success = builder.Build(parse_result.nodes);
if (!success) {
// 处理符号表错误
for (const auto& error : builder.GetErrors()) {
std::cerr << error.ToString() << std::endl;
}
return 1;
}
// 4. 使用符号表
auto& registry = builder.GetRegistry();
// 查找符号
auto result = registry.GlobalScope()->Lookup("MyClass");
if (result) {
auto* cls = dynamic_cast<symbol::Class*>(result.symbol);
// 使用类信息...
}
// 查找 Unit
auto unit = registry.FindUnit("System");
if (unit) {
// 使用 Unit 信息...
}
return 0;
}
```
---
## 📝 总结
### 核心理念
1. **分层清晰**:解析 → AST → 符号表,每层职责明确
2. **错误容忍**:收集所有错误,不因一个错误而停止
3. **三阶段构建**:收集 → 解析 → 验证,逐步完善符号表
4. **类型安全**:使用 variant, dynamic_cast 等确保类型安全
5. **资源管理**:使用智能指针和 RAII 自动管理资源
### 扩展点
- **新的 AST 节点**:在 types.hpp 添加类型,在 deserializer 添加解析
- **新的符号类型**:在 symbol.hpp 添加类型,在 factory 添加创建方法
- **新的验证规则**:在 validator 添加验证方法
- **新的工具函数**:在 utils/ 添加工具类
### 最佳实践
- 保持模块职责单一
- 使用前向声明减少编译依赖
- 在 .cpp 文件中包含完整定义
- 使用 RAII 管理资源
- 收集错误而非立即中断
+101
View File
@@ -0,0 +1,101 @@
#include "./cache.hpp"
#include "./tree_sitter_utils.hpp"
namespace lsp::language::ast
{
NodeCache::NodeCache(size_t max_size) :
max_size_(max_size)
{
}
const ASTNode* NodeCache::Find(const NodeKey& key)
{
auto it = cache_.find(key);
if (it != cache_.end())
{
// 缓存命中,更新LRU
Touch(key, it->second.lru_iter);
++hit_count_;
return &it->second.node;
}
++miss_count_;
return nullptr;
}
void NodeCache::Insert(const NodeKey& key, const ASTNode& node)
{
auto it = cache_.find(key);
if (it != cache_.end())
{
// 键已存在,更新值和LRU
it->second.node = node;
Touch(key, it->second.lru_iter);
return;
}
// 检查是否需要淘汰
if (cache_.size() >= max_size_)
{
EvictLRU();
}
// 插入新条目
lru_list_.push_front(key);
cache_[key] = CacheEntry{ node, lru_list_.begin() };
}
void NodeCache::Clear()
{
cache_.clear();
lru_list_.clear();
ResetStats();
}
void NodeCache::EvictLRU()
{
if (lru_list_.empty())
return;
// 移除最久未使用的(列表尾部)
const NodeKey& evict_key = lru_list_.back();
cache_.erase(evict_key);
lru_list_.pop_back();
}
void NodeCache::Touch([[maybe_unused]] const NodeKey& key, KeyIter iter)
{
// 将元素移到列表前面(最近使用)
lru_list_.splice(lru_list_.begin(), lru_list_, iter);
}
NodeKey NodeCache::MakeKey(const ASTNode& node)
{
return std::visit([](auto&& arg) -> NodeKey {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::monostate>)
{
return NodeKey{ 0, 0, "" };
}
else
{
return NodeKey{
arg.location.start_byte,
arg.location.end_byte,
arg.node_type
};
}
},
node);
}
NodeKey NodeCache::MakeKey(TSNode ts_node)
{
return NodeKey{
ts_node_start_byte(ts_node),
ts_node_end_byte(ts_node),
std::string(ts::Type(ts_node))
};
}
}
+94
View File
@@ -0,0 +1,94 @@
#pragma once
#include <unordered_map>
#include <list>
#include <cstddef>
#include "./types.hpp"
extern "C" {
#include <tree_sitter/api.h>
}
namespace lsp::language::ast
{
// ==================== 缓存键 ====================
struct NodeKey
{
uint32_t start_byte;
uint32_t end_byte;
std::string node_type;
inline bool operator==(const NodeKey& other) const
{
return start_byte == other.start_byte &&
end_byte == other.end_byte &&
node_type == other.node_type;
}
};
struct NodeKeyHash
{
inline size_t operator()(const NodeKey& key) const
{
return std::hash<uint32_t>()(key.start_byte) ^
(std::hash<uint32_t>()(key.end_byte) << 1) ^
(std::hash<std::string>()(key.node_type) << 2);
}
};
// ==================== LRU 缓存(重构 1====================
class NodeCache
{
public:
explicit NodeCache(size_t max_size = 1000);
const ASTNode* Find(const NodeKey& key);
void Insert(const NodeKey& key, const ASTNode& node);
void Clear();
inline size_t Size() const { return cache_.size(); }
inline void SetMaxSize(size_t max_size) { max_size_ = max_size; }
inline size_t GetMaxSize() const { return max_size_; }
// 缓存统计
inline size_t HitCount() const { return hit_count_; }
inline size_t MissCount() const { return miss_count_; }
inline double HitRate() const
{
size_t total = hit_count_ + miss_count_;
return total > 0 ? static_cast<double>(hit_count_) / total : 0.0;
}
// 重置统计
inline void ResetStats()
{
hit_count_ = 0;
miss_count_ = 0;
}
static NodeKey MakeKey(const ASTNode& node);
static NodeKey MakeKey(TSNode ts_node);
private:
// LRU 列表:最近使用的在前面
using KeyList = std::list<NodeKey>;
using KeyIter = KeyList::iterator;
struct CacheEntry
{
ASTNode node;
KeyIter lru_iter;
};
void EvictLRU();
void Touch(const NodeKey& key, KeyIter iter);
size_t max_size_;
KeyList lru_list_;
std::unordered_map<NodeKey, CacheEntry, NodeKeyHash> cache_;
// 统计信息
size_t hit_count_ = 0;
size_t miss_count_ = 0;
};
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,133 @@
#pragma once
#include <functional>
#include <unordered_map>
#include <memory>
#include "./types.hpp"
#include "./tree_sitter_utils.hpp"
#include "./cache.hpp"
namespace lsp::language::ast
{
// ==================== 增量解析结果 ====================
struct IncrementalParseResult
{
ParseResult result;
std::vector<size_t> changed_indices;
std::vector<size_t> reused_indices;
inline size_t ChangedCount() const { return changed_indices.size(); }
inline size_t ReusedCount() const { return reused_indices.size(); }
inline size_t TotalCount() const { return result.nodes.size(); }
inline double ReuseRate() const
{
return TotalCount() > 0 ? static_cast<double>(ReusedCount()) / TotalCount() : 0.0;
}
};
class Deserializer
{
public:
Deserializer();
~Deserializer();
// 基础解析(不使用缓存)
ParseResult Parse(TSNode root, const std::string& source);
// 增量解析(自动复用缓存)
IncrementalParseResult ParseIncremental(TSNode root, const std::string& source);
// 缓存管理
void ClearCache();
size_t CacheSize() const;
void SetCacheMaxSize(size_t max_size);
// 缓存统计
double CacheHitRate() const;
void ResetCacheStats();
private:
std::unique_ptr<NodeCache> cache_;
void ParseChildWithCache(TSNode child, const std::string& source, IncrementalParseResult& result);
};
namespace detail
{
using ParseFunc = std::function<Result<ASTNode>(TSNode, const std::string&)>;
// 获取解析函数映射表
const std::unordered_map<std::string, ParseFunc>& GetParseFuncMap();
// 辅助函数
template<typename T>
inline void InitNode(T& node, TSNode ts_node)
{
node.location = ts::NodeLocation(ts_node);
node.node_type = std::string(ts::Type(ts_node));
}
template<typename T>
inline bool ExtractNameAndLocation(T& node, TSNode ts_node, const std::string& source)
{
TSNode name_node = ts::FieldChild(ts_node, "name");
if (ts::IsNull(name_node))
return false;
node.name = ts::Text(name_node, source);
node.name_location = ts::NodeLocation(name_node);
return !node.name.empty();
}
Result<std::string> GetRequiredField(TSNode node, std::string_view field, const std::string& source, const std::string& error_msg);
Result<std::string> ParseType(TSNode node, const std::string& source);
Result<Signature> ParseSignature(TSNode node, const std::string& source);
Result<std::vector<Parameter>> ParseParameters(TSNode node, const std::string& source);
Result<Block> ParseBlock(TSNode node, const std::string& source);
Access ParseAccess(std::string_view text);
ParseError MakeError(TSNode node, const std::string& message, ErrorSeverity severity = ErrorSeverity::Error);
template<typename T>
inline std::vector<Result<T>> SplitVariableDeclaration(
TSNode node,
const std::string& source,
std::function<Result<T>(TSNode, const std::string&, const std::string&, TSNode)> parse_func)
{
std::vector<Result<T>> results;
auto names = ts::FieldSummaries(node, "name", source);
for (const auto& name_summary : names)
{
results.push_back(parse_func(node, source, name_summary.text, name_summary.node));
}
return results;
}
void ParseClassMembers(TSNode body_node, const std::string& source, ClassDefinition& def);
void ParseClassVariableMember(TSNode node, const std::string& source, Access current_access, ClassDefinition& def);
void ParseClassMethodMember(TSNode node, const std::string& source, Access current_access, ClassDefinition& def);
void ParseClassPropertyMember(TSNode node, const std::string& source, Access current_access, ClassDefinition& def);
ParseResult ParseStatements(TSNode node, const std::string& source);
ParseResult ParseChildren(const std::vector<TSNode>& children, const std::string& source);
}
// ==================== 顶层解析 API ====================
Result<ASTNode> ParseNode(TSNode node, const std::string& source);
ParseResult ParseRoot(TSNode root, const std::string& source);
// ==================== 具体类型解析函数 ====================
Result<VarDeclaration> ParseVarDeclaration(TSNode node, const std::string& source, const std::string& var_name, TSNode name_node);
Result<StaticDeclaration> ParseStaticDeclaration(TSNode node, const std::string& source, const std::string& var_name, TSNode name_node);
Result<GlobalDeclaration> ParseGlobalDeclaration(TSNode node, const std::string& source, const std::string& var_name, TSNode name_node);
Result<ConstDeclaration> ParseConstDeclaration(TSNode node, const std::string& source);
Result<AssignmentStatement> ParseAssignmentStatement(TSNode node, const std::string& source);
Result<FunctionDefinition> ParseFunctionDefinition(TSNode node, const std::string& source);
Result<ClassDefinition> ParseClassDefinition(TSNode node, const std::string& source);
Result<Method> ParseMethod(TSNode node, const std::string& source);
Result<ExternalMethod> ParseExternalMethod(TSNode node, const std::string& source);
Result<Property> ParseProperty(TSNode node, const std::string& source);
Result<UnitDefinition> ParseUnitDefinition(TSNode node, const std::string& source);
Result<UsesClause> ParseUsesClause(TSNode node, const std::string& source);
}
@@ -0,0 +1,140 @@
#include "./tree_sitter_utils.hpp"
namespace lsp::language::ast::ts
{
// ==================== 字符串池实现 ====================
StringPool& StringPool::Instance()
{
static StringPool instance;
return instance;
}
std::string_view StringPool::Intern(std::string_view str)
{
auto it = pool_.find(std::string(str));
if (it != pool_.end())
{
return *it;
}
auto [inserted_it, _] = pool_.insert(std::string(str));
return *inserted_it;
}
void StringPool::Clear()
{
pool_.clear();
}
// ==================== 文本提取 ====================
std::string Text(TSNode node, std::string_view source)
{
uint32_t start = ts_node_start_byte(node);
uint32_t end = ts_node_end_byte(node);
if (start >= source.length() || end > source.length() || start >= end)
return "";
return std::string(source.substr(start, end - start));
}
std::string Text(TSNode node, const std::string& source)
{
return Text(node, std::string_view(source));
}
Location NodeLocation(TSNode node)
{
TSPoint start = ts_node_start_point(node);
TSPoint end = ts_node_end_point(node);
return Location{
static_cast<uint32_t>(start.row),
static_cast<uint32_t>(start.column),
static_cast<uint32_t>(end.row),
static_cast<uint32_t>(end.column),
ts_node_start_byte(node),
ts_node_end_byte(node)
};
}
std::string FieldText(TSNode node, std::string_view field_name, std::string_view source)
{
TSNode field = FieldChild(node, field_name);
return IsNull(field) ? "" : Text(field, source);
}
std::string FieldText(TSNode node, std::string_view field_name, const std::string& source)
{
return FieldText(node, field_name, std::string_view(source));
}
std::vector<TSNode> Children(TSNode node)
{
std::vector<TSNode> children;
uint32_t count = ts_node_child_count(node);
children.reserve(count);
for (uint32_t i = 0; i < count; i++)
children.push_back(ts_node_child(node, i));
return children;
}
std::vector<TSNode> FieldChildren(TSNode node, std::string_view field_name)
{
std::vector<TSNode> result;
uint32_t count = ts_node_child_count(node);
for (uint32_t i = 0; i < count; i++)
{
const char* field = ts_node_field_name_for_child(node, i);
if (field && field_name == field)
result.push_back(ts_node_child(node, i));
}
return result;
}
std::vector<NodeSummary> ChildSummaries(TSNode node, std::string_view source)
{
std::vector<NodeSummary> result;
uint32_t count = ts_node_child_count(node);
for (uint32_t i = 0; i < count; i++)
{
TSNode child = ts_node_child(node, i);
const char* field_name = ts_node_field_name_for_child(node, i);
result.push_back(NodeSummary{
.node = child,
.field = field_name ? field_name : "",
.type = std::string(Type(child)),
.text = Text(child, source) });
}
return result;
}
std::vector<NodeSummary> ChildSummaries(TSNode node, const std::string& source)
{
return ChildSummaries(node, std::string_view(source));
}
std::vector<NodeSummary> FieldSummaries(TSNode node, std::string_view field_name, std::string_view source)
{
std::vector<NodeSummary> result;
uint32_t count = ts_node_child_count(node);
for (uint32_t i = 0; i < count; i++)
{
TSNode child = ts_node_child(node, i);
const char* field = ts_node_field_name_for_child(node, i);
if (field && field_name == field)
{
result.push_back(NodeSummary{
.node = child,
.field = field,
.type = std::string(Type(child)),
.text = Text(child, source) });
}
}
return result;
}
std::vector<NodeSummary> FieldSummaries(TSNode node, std::string_view field_name, const std::string& source)
{
return FieldSummaries(node, field_name, std::string_view(source));
}
}
@@ -0,0 +1,104 @@
#pragma once
#include <string>
#include <string_view>
#include <vector>
#include <unordered_set>
#include "./types.hpp"
extern "C" {
#include <tree_sitter/api.h>
}
namespace lsp::language::ast::ts
{
class StringPool
{
public:
static StringPool& Instance();
// 缓存字符串,返回池中的引用
std::string_view Intern(std::string_view str);
void Clear();
size_t Size() const { return pool_.size(); }
private:
StringPool() = default;
StringPool(const StringPool&) = delete;
StringPool& operator=(const StringPool&) = delete;
private:
std::unordered_set<std::string> pool_;
};
// ==================== 节点摘要 ====================
struct NodeSummary
{
TSNode node;
std::string field;
std::string type;
std::string text;
};
// ==================== 基础查询 ====================
// 获取节点文本(使用 string_view 优化)
std::string Text(TSNode node, std::string_view source);
std::string Text(TSNode node, const std::string& source);
// 获取节点类型(使用字符串池)
inline std::string_view Type(TSNode node);
// 获取节点位置
Location NodeLocation(TSNode node);
// 节点状态检查
inline bool IsNull(TSNode node);
inline bool IsComment(TSNode node);
// ==================== 字段操作 ====================
inline TSNode FieldChild(TSNode node, std::string_view field_name);
std::string FieldText(TSNode node, std::string_view field_name, std::string_view source);
std::string FieldText(TSNode node, std::string_view field_name, const std::string& source);
inline bool HasField(TSNode node, std::string_view field_name);
// ==================== 子节点操作 ====================
std::vector<TSNode> Children(TSNode node);
std::vector<TSNode> FieldChildren(TSNode node, std::string_view field_name);
std::vector<NodeSummary> ChildSummaries(TSNode node, std::string_view source);
std::vector<NodeSummary> ChildSummaries(TSNode node, const std::string& source);
std::vector<NodeSummary> FieldSummaries(TSNode node, std::string_view field_name, std::string_view source);
std::vector<NodeSummary> FieldSummaries(TSNode node, std::string_view field_name, const std::string& source);
// ==================== Inline 实现 ====================
inline std::string_view Type(TSNode node)
{
const char* type_str = ts_node_type(node);
return StringPool::Instance().Intern(type_str);
}
inline bool IsNull(TSNode node)
{
return ts_node_is_null(node);
}
inline bool IsComment(TSNode node)
{
std::string_view type = Type(node);
return type == "line_comment" || type == "block_comment" || type == "nested_comment";
}
inline TSNode FieldChild(TSNode node, std::string_view field_name)
{
return ts_node_child_by_field_name(node, field_name.data(), field_name.length());
}
inline bool HasField(TSNode node, std::string_view field_name)
{
return !IsNull(FieldChild(node, field_name));
}
}
+334
View File
@@ -0,0 +1,334 @@
#pragma once
#include <string>
#include <vector>
#include <optional>
#include <variant>
#include <cstdint>
#include <stdexcept>
namespace lsp::language::ast
{
// ==================== 基础类型 ====================
struct Location
{
uint32_t start_line = 0;
uint32_t start_column = 0;
uint32_t end_line = 0;
uint32_t end_column = 0;
uint32_t start_byte = 0;
uint32_t end_byte = 0;
};
struct Node
{
Location location;
std::string node_type;
};
struct Expression
{
Location location;
std::string node_type;
std::string text;
};
struct Parameter
{
Location location;
Location name_location;
std::string name;
std::optional<std::string> type_name;
std::optional<std::string> default_value;
bool is_var = false;
bool is_out = false;
};
struct Signature
{
std::vector<Parameter> parameters;
std::optional<std::string> return_type;
};
// ==================== 前向声明 ====================
struct VarDeclaration;
struct StaticDeclaration;
struct GlobalDeclaration;
struct ConstDeclaration;
struct AssignmentStatement;
struct FunctionDefinition;
struct ClassDefinition;
struct Method;
struct ExternalMethod;
struct ConstructorDeclaration;
struct DestructorDeclaration;
struct Property;
struct UsesClause;
struct Block;
struct UnitDefinition;
using ASTNode = std::variant<
std::monostate,
FunctionDefinition,
ClassDefinition,
VarDeclaration,
StaticDeclaration,
GlobalDeclaration,
ConstDeclaration,
AssignmentStatement,
Method,
ExternalMethod,
Property,
UsesClause,
UnitDefinition,
Expression,
Block>;
// ==================== AST 节点定义 ====================
struct Block
{
Location location;
std::string node_type;
std::vector<ASTNode> statements;
};
struct VarDeclaration
{
Location location;
Location name_location;
std::string node_type;
std::string name;
std::optional<std::string> type_name;
std::optional<Expression> value;
};
struct StaticDeclaration
{
Location location;
Location name_location;
std::string node_type;
std::string name;
std::optional<std::string> type_name;
std::optional<Expression> value;
};
struct GlobalDeclaration
{
Location location;
Location name_location;
std::string node_type;
std::string name;
std::optional<std::string> type_name;
std::optional<Expression> value;
};
struct ConstDeclaration
{
Location location;
Location name_location;
std::string node_type;
std::string name;
std::optional<std::string> type_name;
Expression value;
};
struct AssignmentStatement
{
Location location;
Location name_location;
std::string node_type;
std::string name;
Expression value;
};
struct FunctionDefinition
{
Location location;
Location name_location;
std::string node_type;
std::string name;
bool is_overload = false;
Signature signature;
Block body;
};
enum class Access
{
kPublic,
kProtected,
kPrivate
};
struct Property
{
Location location;
Location name_location;
std::string node_type;
std::string name;
std::optional<std::string> type_name;
std::optional<std::string> getter;
std::optional<std::string> setter;
};
enum class Modifier
{
kNone,
kVirtual,
kOverride,
kOverload
};
struct Method
{
Location location;
Location name_location;
std::string node_type;
std::string name;
Signature signature;
bool is_class_method = false;
Modifier modifier = Modifier::kNone;
std::optional<Block> body;
};
struct ExternalMethod
{
Location location;
Location name_location;
std::string node_type;
std::string class_name;
std::string method_name;
Signature signature;
bool is_class_method = false;
bool is_operator = false;
std::string operator_symbol;
Modifier modifier = Modifier::kNone;
Block body;
};
struct ConstructorDeclaration
{
Location location;
Location name_location;
std::string node_type;
Signature signature;
std::optional<Block> body;
};
struct DestructorDeclaration
{
Location location;
Location name_location;
std::string node_type;
std::optional<Block> body;
};
struct ClassMember
{
Access access = Access::kPublic;
std::variant<
std::monostate,
VarDeclaration,
StaticDeclaration,
Method,
ConstructorDeclaration,
DestructorDeclaration,
Property>
content;
};
struct ClassDefinition
{
Location location;
Location name_location;
std::string node_type;
std::string name;
std::vector<std::string> parents;
std::vector<ClassMember> members;
};
struct UsesClause
{
Location location;
std::string node_type;
std::vector<std::string> units;
};
struct UnitDefinition
{
Location location;
Location name_location;
std::string node_type;
std::string name;
std::optional<UsesClause> uses;
std::vector<ASTNode> interface_statements;
std::vector<ASTNode> implementation_statements;
std::vector<ASTNode> initialization_statements;
std::vector<ASTNode> finalization_statements;
};
// ==================== 错误处理 ====================
enum class ErrorSeverity
{
Warning,
Error,
Fatal
};
struct ParseError
{
Location location;
std::string node_type;
std::string message;
ErrorSeverity severity = ErrorSeverity::Error;
};
struct ParseResult
{
std::vector<ASTNode> nodes;
std::vector<ParseError> errors;
inline bool HasErrors() const { return !errors.empty(); }
inline bool IsSuccess() const { return errors.empty(); }
};
// ==================== Result<T> 模板 ====================
template<typename T>
class Result
{
public:
static Result<T> Ok(T&& val)
{
return { true, std::move(val), "", ErrorSeverity::Error };
}
static Result<T> Err(const std::string& msg, ErrorSeverity sev = ErrorSeverity::Error)
{
return { false, std::nullopt, msg, sev };
}
inline bool IsOk() const { return success; }
inline bool IsErr() const { return !success; }
T Unwrap() &&
{
if (!success)
throw std::runtime_error("Unwrap on error: " + error);
return std::move(value).value();
}
T UnwrapOr(T&& default_val) &&
{
return success ? std::move(*value) : std::move(default_val);
}
bool success = false;
std::optional<T> value;
std::string error;
ErrorSeverity severity = ErrorSeverity::Error;
};
}
+126
View File
@@ -0,0 +1,126 @@
#include "./repo.hpp"
namespace lsp::language::keyword
{
Repo& Repo::Instance()
{
static Repo instance;
return instance;
}
Repo::Repo()
{
Load();
}
std::vector<Info> Repo::GetAll()
{
std::vector<Info> keyword;
keyword.reserve(keywords_.size());
for (const auto& [key, value] : keywords_)
keyword.push_back(value);
return keyword;
}
std::vector<Info> Repo::FindByPrefix(std::string_view prefix)
{
std::vector<Info> keyword;
for (const auto& [key, value] : keywords_)
{
if (key.starts_with(prefix))
keyword.push_back(value);
}
return keyword;
}
std::optional<Info> Repo::FindByName(std::string_view name)
{
auto target = keywords_.find(std::string(name));
if (target == keywords_.end())
return std::nullopt;
return target->second;
}
void Repo::Load()
{
keywords_.reserve(200);
LoadProgramStructure();
LoadDataTypes();
LoadClasses();
LoadControlFlow();
LoadOperators();
LoadSql();
LoadBuiltins();
LoadConstants();
}
void Repo::LoadProgramStructure()
{
keywords_["program"] = {"program", Kind::kProgramStructure, ""};
keywords_["function"] = {"function", Kind::kProgramStructure, ""};
keywords_["procedure"] = {"procedure", Kind::kProgramStructure, ""};
keywords_["unit"] = {"unit", Kind::kProgramStructure, ""};
keywords_["uses"] = {"uses", Kind::kProgramStructure, ""};
keywords_["implementation"] = {"implementation", Kind::kProgramStructure, ""};
keywords_["interface"] = {"interface", Kind::kProgramStructure, ""};
keywords_["initialization"] = {"initialization", Kind::kProgramStructure, ""};
keywords_["finalization"] = {"finalization", Kind::kProgramStructure, ""};
}
void Repo::LoadDataTypes()
{
keywords_["string"] = {"string", Kind::kDataTypes, ""};
keywords_["integer"] = {"integer", Kind::kDataTypes, ""};
keywords_["boolean"] = {"boolean", Kind::kDataTypes, ""};
keywords_["int64"] = {"int64", Kind::kDataTypes, ""};
keywords_["real"] = {"real", Kind::kDataTypes, ""};
keywords_["array"] = {"array", Kind::kDataTypes, ""};
}
void Repo::LoadClasses()
{
keywords_["type"] = {"type", Kind::kClassTypes, ""};
keywords_["class"] = {"class", Kind::kClassTypes, ""};
keywords_["new"] = {"new", Kind::kClassTypes, ""};
}
void Repo::LoadControlFlow()
{
keywords_["if"] = {"if", Kind::kConditionals, ""};
keywords_["for"] = {"for", Kind::kLoops, ""};
keywords_["while"] = {"while", Kind::kLoops, ""};
keywords_["case"] = {"case", Kind::kConditionals, ""};
}
void Repo::LoadOperators()
{
keywords_["and"] = {"and", Kind::kLogicalOperators, ""};
keywords_["or"] = {"or", Kind::kLogicalOperators, ""};
keywords_["div"] = {"div", Kind::kArithmeticOperators, ""};
keywords_["mod"] = {"mod", Kind::kArithmeticOperators, ""};
}
void Repo::LoadSql()
{
keywords_["select"] = {"select", Kind::kSqlControl, ""};
keywords_["update"] = {"update", Kind::kSqlControl, ""};
}
void Repo::LoadBuiltins()
{
keywords_["echo"] = {"echo", Kind::kBuiltinFunctions, ""};
keywords_["mtic"] = {"mtic", Kind::kBuiltinFunctions, ""};
keywords_["mtoc"] = {"mtoc", Kind::kBuiltinFunctions, ""};
}
void Repo::LoadConstants()
{
keywords_["true"] = {"true", Kind::kBooleanConstants, ""};
keywords_["false"] = {"false", Kind::kBooleanConstants, ""};
keywords_["nil"] = {"nil", Kind::kNullConstants, ""};
keywords_["inf"] = {"inf", Kind::kMathConstants, ""};
keywords_["nan"] = {"nan", Kind::kMathConstants, ""};
}
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include <optional>
#include <string_view>
#include <unordered_map>
#include <vector>
#include "./types.hpp"
namespace lsp::language::keyword
{
class Repo
{
public:
Repo(const Repo&) = delete;
Repo& operator=(const Repo&) = delete;
static Repo& Instance();
std::vector<Info> GetAll();
std::vector<Info> FindByPrefix(std::string_view prefix);
std::optional<Info> FindByName(std::string_view name);
private:
Repo();
void Load();
void LoadProgramStructure();
void LoadDataTypes();
void LoadClasses();
void LoadControlFlow();
void LoadOperators();
void LoadSql();
void LoadBuiltins();
void LoadConstants();
// std::unordered_map<std::string, Info, std::hash<std::string_view>, std::equal_to<>> keywords_;
std::unordered_map<std::string, Info> keywords_;
};
}
@@ -1,11 +1,11 @@
#pragma once
#include <string>
#include <optional>
#include "../protocol/protocol.hpp"
#include "../../protocol/protocol.hpp"
namespace tsl
namespace lsp::language::keyword
{
enum class KeywordCategory
enum class Kind
{
kProgramStructure, // program, function, procedure, unit, uses, implementation, interface, initialization, finalization
kDataTypes, // string, integer, boolean, int64, real, array
@@ -39,10 +39,10 @@ namespace tsl
kNullConstants // nil
};
struct KeywordInfo
struct Info
{
std::string keyword;
KeywordCategory category;
Kind category;
std::string description;
};
-297
View File
@@ -1,297 +0,0 @@
#include "./keyword_manager.hpp"
namespace tsl
{
KeywordManager& KeywordManager::GetInstance()
{
static KeywordManager instance;
return instance;
}
KeywordManager::KeywordManager()
{
InitKeywords();
}
std::vector<KeywordInfo> KeywordManager::GetAllKeywords()
{
std::vector<KeywordInfo> keyword;
keyword.reserve(keywords_.size());
for (const auto& [key, value] : keywords_)
keyword.push_back(value);
return keyword;
}
std::vector<KeywordInfo> KeywordManager::GetKeyWordByPrefix(std::string prefix)
{
std::vector<KeywordInfo> keyword;
for (const auto& [key, value] : keywords_)
{
if (key.starts_with(prefix))
keyword.push_back(value);
}
return keyword;
}
std::optional<KeywordInfo> KeywordManager::GetKeywordInfo(std::string key)
{
auto target = keywords_.find(key);
if (target == keywords_.end())
return std::nullopt;
return target->second;
}
void KeywordManager::InitKeywords()
{
keywords_.reserve(200);
InitProgramStructureKeywords();
InitDataTypeKeywords();
InitClassKeywords();
InitControlFlowKeywords();
InitOperatorKeywords();
InitSqlKeywords();
InitBuiltinKeywords();
InitConstantKeywords();
}
void KeywordManager::InitProgramStructureKeywords()
{
keywords_["program"] = {
"program",
KeywordCategory::kProgramStructure,
"## Program\n\n程序开始的入口,一般用户不需要使用,在作为独立的TSL脚本时可以使用。 \n通常来说,倘若编写TSL代码作为CGI执行运行,系统默认以PROGRAM模式运行。虽然TSL可以省略PROGRAM关键字,但是使用PROGRAM关键字可以使得TSL代码里包含子函数.\n\n**例如:**\n```pascal\nprogram Test;\n\tfunction sub1();\n\tbegin\n\t\twriteln('Execute sub1');\n\tend;\nbegin\n\tsub1();\nend.\n```"
};
keywords_["function"] = {
"function",
KeywordCategory::kProgramStructure,
"## Function\n\n函数声明开始,组成类似于FUNCTION XXXX(); BEGIN END;的函数块"
};
keywords_["procedure"] = {
"procedure",
KeywordCategory::kProgramStructure,
"## Procedure\n\n与FUNCTION类似,但是在函数头后不允许加返回类型值"
};
keywords_["unit"] = {
"unit",
KeywordCategory::kProgramStructure,
"## Unit Declaration\n\nDeclares a code unit/module.\n\n**Syntax:**\n```pascal\nunit UnitName;\ninterface\n // public declarations\nimplementation\n // private implementation\nend.\n```"
};
keywords_["uses"] = {
"uses",
KeywordCategory::kProgramStructure,
"## Uses Clause\n\nImports external units/modules.\n\n**Syntax:**\n```pascal\nuses Unit1, Unit2, Unit3;\n```\n\n**Example:**\n```pascal\nuses System, SysUtils, Classes;\n```"
};
keywords_["implementation"] = {
"implementation",
KeywordCategory::kProgramStructure,
"## Implementation Section\n\nMarks the beginning of the private implementation section in a unit.\n\n**Usage:**\n```pascal\nunit MyUnit;\ninterface\n // public interface\nimplementation\n // private implementation\nend.\n```"
};
keywords_["interface"] = {
"interface",
KeywordCategory::kProgramStructure,
"## Interface Section\n\nMarks the public interface section in a unit.\n\n**Usage:**\n```pascal\nunit MyUnit;\ninterface\n // public declarations\n function PublicFunction: integer;\nimplementation\nend.\n```"
};
keywords_["initialization"] = {
"initialization",
KeywordCategory::kProgramStructure,
"## Initialization Section\n\nCode executed when the unit is first loaded.\n\n**Usage:**\n```pascal\nunit MyUnit;\ninterface\nimplementation\ninitialization\n // initialization code\nend.\n```"
};
keywords_["finalization"] = {
"finalization",
KeywordCategory::kProgramStructure,
"## Finalization Section\n\nCode executed when the program terminates.\n\n**Usage:**\n```pascal\nunit MyUnit;\ninterface\nimplementation\ninitialization\n // setup code\nfinalization\n // cleanup code\nend.\n```"
};
}
void KeywordManager::InitDataTypeKeywords()
{
keywords_["string"] = {
"string",
KeywordCategory::kDataTypes,
"## String Type\n\nVariable-length string data type.\n\n**Example:**\n```pascal\nvar\n myString: string;\nbegin\n myString := 'Hello World';\nend;\n```\n\n**Note:** Supports Unicode and automatic memory management."
};
keywords_["integer"] = {
"integer",
KeywordCategory::kDataTypes,
"## Integer Type\n\n32-bit signed integer data type.\n\n**Range:** -2,147,483,648 to 2,147,483,647\n\n**Example:**\n```pascal\nvar\n count: integer;\nbegin\n count := 42;\nend;\n```"
};
keywords_["boolean"] = {
"boolean",
KeywordCategory::kDataTypes,
"## Boolean Type\n\nLogical data type with values `true` or `false`.\n\n**Example:**\n```pascal\nvar\n isValid: boolean;\nbegin\n isValid := true;\n if isValid then\n echo('Valid!');\nend;\n```"
};
keywords_["int64"] = {
"int64",
KeywordCategory::kDataTypes,
"## Int64 Type\n\n64-bit signed integer data type.\n\n**Range:** -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807\n\n**Example:**\n```pascal\nvar\n bigNumber: int64;\nbegin\n bigNumber := 1234567890123456789;\nend;\n```"
};
keywords_["real"] = {
"real",
KeywordCategory::kDataTypes,
"## Real Type\n\nFloating-point number data type.\n\n**Example:**\n```pascal\nvar\n price: real;\nbegin\n price := 19.99;\nend;\n```"
};
keywords_["array"] = {
"array",
KeywordCategory::kDataTypes,
"## Array Type\n\nCollection of elements of the same type.\n\n**Syntax:**\n```pascal\narray[IndexType] of ElementType\n```\n\n**Examples:**\n```pascal\nvar\n numbers: array[1..10] of integer;\n names: array of string; // dynamic array\nbegin\n numbers[1] := 42;\nend;\n```"
};
}
void KeywordManager::InitClassKeywords()
{
keywords_["type"] = {
"type",
KeywordCategory::kClassTypes,
"## Type Declaration\n\nDeclares custom data types.\n\n**Syntax:**\n```pascal\ntype\n TypeName = TypeDefinition;\n```\n\n**Example:**\n```pascal\ntype\n TPoint = record\n X, Y: integer;\n end;\n \n TMyClass = class\n // class members\n end;\n```"
};
keywords_["class"] = {
"class",
KeywordCategory::kClassTypes,
"## Class Declaration\n\nDeclares an object-oriented class.\n\n**Syntax:**\n```pascal\ntype\n TClassName = class(TBaseClass)\n private\n // private members\n public\n // public members\n end;\n```\n\n**Example:**\n```pascal\ntype\n TPerson = class\n private\n FName: string;\n public\n constructor Create(AName: string);\n property Name: string read FName write FName;\n end;\n```"
};
keywords_["new"] = {
"new",
KeywordCategory::kClassTypes,
"## New Instance\n\nCreates a new instance of a class.\n\n**Syntax:**\n```pascal\nInstanceVar := ClassName.Create();\n```\n\n**Example:**\n```pascal\nvar\n person: TPerson;\nbegin\n person := TPerson.Create('John');\n try\n // use person\n finally\n person.Free;\n end;\nend;\n```"
};
}
void KeywordManager::InitControlFlowKeywords()
{
keywords_["if"] = {
"if",
KeywordCategory::kConditionals,
"## If Statement\n\nConditional execution based on a boolean expression.\n\n**Syntax:**\n```pascal\nif condition then\n statement\nelse\n statement;\n```\n\n**Example:**\n```pascal\nif age >= 18 then\n echo('Adult')\nelse\n echo('Minor');\n```\n\n**Multi-line:**\n```pascal\nif score >= 90 then\nbegin\n grade := 'A';\n echo('Excellent!');\nend;\n```"
};
keywords_["for"] = {
"for",
KeywordCategory::kLoops,
"## For Loop\n\nIterates over a range of values.\n\n**Syntax:**\n```pascal\nfor variable := startValue to endValue do\n statement;\n \nfor variable := startValue downto endValue do\n statement;\n```\n\n**Examples:**\n```pascal\n// Forward loop\nfor i := 1 to 10 do\n echo(i);\n \n// Reverse loop\nfor i := 10 downto 1 do\n echo(i);\n \n// Array iteration\nfor i := Low(myArray) to High(myArray) do\n echo(myArray[i]);\n```"
};
keywords_["while"] = {
"while",
KeywordCategory::kLoops,
"## While Loop\n\nRepeats while a condition is true.\n\n**Syntax:**\n```pascal\nwhile condition do\n statement;\n```\n\n**Example:**\n```pascal\ni := 0;\nwhile i < 10 do\nbegin\n echo(i);\n i := i + 1;\nend;\n```\n\n**Note:** The condition is checked before each iteration."
};
keywords_["case"] = {
"case",
KeywordCategory::kConditionals,
"## Case Statement\n\nMulti-way conditional based on value matching.\n\n**Syntax:**\n```pascal\ncase expression of\n value1: statement1;\n value2: statement2;\n else\n defaultStatement;\nend;\n```\n\n**Example:**\n```pascal\ncase dayOfWeek of\n 1: echo('Monday');\n 2: echo('Tuesday');\n 3: echo('Wednesday');\n 4: echo('Thursday');\n 5: echo('Friday');\n 6, 7: echo('Weekend');\n else\n echo('Invalid day');\nend;\n```"
};
}
void KeywordManager::InitOperatorKeywords()
{
keywords_["and"] = {
"and",
KeywordCategory::kLogicalOperators,
"## Logical AND\n\nLogical conjunction operator.\n\n**Truth Table:**\n| A | B | A and B |\n|---|---|--------|\n| T | T | T |\n| T | F | F |\n| F | T | F |\n| F | F | F |\n\n**Example:**\n```pascal\nif (age >= 18) and (hasLicense) then\n echo('Can drive');\n```"
};
keywords_["or"] = {
"or",
KeywordCategory::kLogicalOperators,
"## Logical OR\n\nLogical disjunction operator.\n\n**Truth Table:**\n| A | B | A or B |\n|---|---|-------|\n| T | T | T |\n| T | F | T |\n| F | T | T |\n| F | F | F |\n\n**Example:**\n```pascal\nif (isAdmin) or (isOwner) then\n echo('Has permission');\n```"
};
keywords_["div"] = {
"div",
KeywordCategory::kArithmeticOperators,
"## Integer Division\n\nPerforms integer division (truncates decimal part).\n\n**Example:**\n```pascal\nvar result: integer;\nbegin\n result := 17 div 5; // result = 3\n result := 20 div 4; // result = 5\nend;\n```\n\n**Note:** Use `/` for real division, `div` for integer division."
};
keywords_["mod"] = {
"mod",
KeywordCategory::kArithmeticOperators,
"## Modulo Operator\n\nReturns the remainder of integer division.\n\n**Example:**\n```pascal\nvar remainder: integer;\nbegin\n remainder := 17 mod 5; // remainder = 2\n remainder := 20 mod 4; // remainder = 0\n \n // Check if number is even\n if (number mod 2) = 0 then\n echo('Even number');\nend;\n```"
};
}
void KeywordManager::InitSqlKeywords()
{
keywords_["select"] = {
"select",
KeywordCategory::kSqlControl,
"## SQL SELECT Statement\n\nRetrieves data from database tables.\n\n**Syntax:**\n```sql\nSELECT column1, column2, ...\nFROM table_name\nWHERE condition\nORDER BY column;\n```\n\n**Examples:**\n```sql\n-- Basic select\nSELECT name, age FROM users;\n\n-- With condition\nSELECT * FROM products WHERE price > 100;\n\n-- With ordering\nSELECT name, salary FROM employees ORDER BY salary DESC;\n```"
};
keywords_["update"] = {
"update",
KeywordCategory::kSqlControl,
"## SQL UPDATE Statement\n\nModifies existing records in a table.\n\n**Syntax:**\n```sql\nUPDATE table_name\nSET column1 = value1, column2 = value2, ...\nWHERE condition;\n```\n\n**Examples:**\n```sql\n-- Update single record\nUPDATE users SET age = 30 WHERE id = 1;\n\n-- Update multiple columns\nUPDATE products \nSET price = 99.99, category = 'Electronics'\nWHERE id = 100;\n```\n\n**⚠️ Warning:** Always use WHERE clause to avoid updating all records!"
};
}
void KeywordManager::InitBuiltinKeywords()
{
keywords_["echo"] = {
"echo",
KeywordCategory::kBuiltinFunctions,
"## Echo Function\n\nOutputs text to the console or output stream.\n\n**Syntax:**\n```pascal\necho(expression);\necho(format, args...);\n```\n\n**Examples:**\n```pascal\necho('Hello World!');\necho('Number: ', 42);\necho('Name: %s, Age: %d', name, age);\n```\n\n**Features:**\n- Supports multiple arguments\n- Automatic type conversion\n- Format string support"
};
keywords_["mtic"] = {
"mtic",
KeywordCategory::kBuiltinFunctions,
"## Timer Start (mtic)\n\nStarts a high-precision timer for performance measurement.\n\n**Usage:**\n```pascal\nmtic(); // Start timer\n// ... code to measure ...\nvar elapsed := mtoc(); // Get elapsed time\necho('Elapsed: ', elapsed, ' seconds');\n```\n\n**Note:** Use with `mtoc()` to measure execution time."
};
keywords_["mtoc"] = {
"mtoc",
KeywordCategory::kBuiltinFunctions,
"## Timer End (mtoc)\n\nReturns elapsed time since last `mtic()` call.\n\n**Returns:** Time in seconds (real number)\n\n**Example:**\n```pascal\nmtic();\nfor i := 1 to 1000000 do\n // some computation\nvar timeElapsed := mtoc();\necho('Loop took: ', timeElapsed, ' seconds');\n```"
};
}
void KeywordManager::InitConstantKeywords()
{
keywords_["true"] = {
"true",
KeywordCategory::kBooleanConstants,
"## Boolean True\n\nRepresents the boolean value **true**.\n\n**Usage:**\n```pascal\nvar\n flag: boolean;\nbegin\n flag := true;\n \n if flag then\n echo('Flag is set!');\nend;\n```\n\n**Note:** Case-insensitive in most Pascal dialects."
};
keywords_["false"] = {
"false",
KeywordCategory::kBooleanConstants,
"## Boolean False\n\nRepresents the boolean value **false**.\n\n**Usage:**\n```pascal\nvar\n isComplete: boolean;\nbegin\n isComplete := false;\n \n while not isComplete do\n begin\n // do work\n isComplete := checkCompletion();\n end;\nend;\n```"
};
keywords_["nil"] = {
"nil",
KeywordCategory::kNullConstants,
"## Nil Constant\n\nRepresents a null/empty pointer or object reference.\n\n**Usage:**\n```pascal\nvar\n obj: TMyClass;\nbegin\n obj := nil; // Initialize to null\n \n if obj <> nil then\n obj.DoSomething();\n \n obj := TMyClass.Create();\n try\n // use obj\n finally\n obj.Free;\n obj := nil; // Clear reference\n end;\nend;\n```\n\n**Best Practice:** Always check for nil before using object references."
};
keywords_["inf"] = {
"inf",
KeywordCategory::kMathConstants,
"## Infinity Constant\n\nRepresents positive mathematical infinity.\n\n**Usage:**\n```pascal\nvar\n result: real;\nbegin\n result := 1.0 / 0.0; // Results in inf\n \n if result = inf then\n echo('Result is infinite');\nend;\n```\n\n**Note:** Use for floating-point calculations and comparisons."
};
keywords_["nan"] = {
"nan",
KeywordCategory::kMathConstants,
"## Not a Number (NaN)\n\nRepresents an undefined or invalid floating-point result.\n\n**Common Causes:**\n- `0.0 / 0.0`\n- `sqrt(-1.0)`\n- `inf - inf`\n\n**Usage:**\n```pascal\nvar\n result: real;\nbegin\n result := sqrt(-1.0); // Results in NaN\n \n if IsNaN(result) then\n echo('Invalid calculation');\nend;\n```\n\n**Note:** NaN ≠ NaN, use `IsNaN()` function for checking."
};
}
}
@@ -1,35 +0,0 @@
#pragma once
#include <optional>
#include <unordered_map>
#include <vector>
#include "./keyword_types.hpp"
namespace tsl
{
class KeywordManager
{
public:
KeywordManager(const KeywordManager&) = delete;
KeywordManager& operator=(const KeywordManager&) = delete;
static KeywordManager& GetInstance();
std::vector<KeywordInfo> GetAllKeywords();
std::vector<KeywordInfo> GetKeyWordByPrefix(std::string prefix);
std::optional<KeywordInfo> GetKeywordInfo(std::string key);
private:
KeywordManager();
void InitKeywords();
void InitProgramStructureKeywords();
void InitDataTypeKeywords();
void InitClassKeywords();
void InitControlFlowKeywords();
void InitOperatorKeywords();
void InitSqlKeywords();
void InitBuiltinKeywords();
void InitConstantKeywords();
std::unordered_map<std::string, KeywordInfo> keywords_;
};
}
@@ -0,0 +1,160 @@
#include "./builder.hpp"
#include "../collector/symbol_collector.hpp"
#include "../collector/incremental_collector.hpp"
#include "../incremental/incremental_engine.hpp"
namespace lsp::language::symbol
{
// ==================== 构造和析构 ====================
SymbolTableBuilder::SymbolTableBuilder() :
incremental_enabled_(false)
{
}
SymbolTableBuilder::~SymbolTableBuilder() = default;
// ==================== 构建接口 ====================
bool SymbolTableBuilder::Build(const std::vector<ast::ASTNode>& nodes)
{
// 清空错误
error_reporter_.Clear();
// 初始化统计信息
stats_ = BuildStatistics{};
stats_.is_incremental = false;
stats_.total_symbols = nodes.size();
// 创建收集上下文
CollectorContext context(registry_, error_reporter_);
// 创建基础收集器并执行
SymbolCollector collector(context);
bool success = collector.Collect(nodes);
// 更新统计信息
stats_.success = success && !error_reporter_.HasErrors();
stats_.new_symbols = stats_.total_symbols;
stats_.reused_symbols = 0;
stats_.reuse_rate = 0.0;
// 完整构建后,如果启用增量,则构建缓存
if (stats_.success && incremental_enabled_ && incremental_engine_)
{
incremental_engine_->BuildCache(registry_);
}
return stats_.success;
}
bool SymbolTableBuilder::BuildIncremental(
const ast::IncrementalParseResult& parse_result)
{
// 检查增量是否启用
if (!incremental_enabled_ || !incremental_engine_)
{
// 增量未启用,退回完整构建
return Build(parse_result.result.nodes);
}
// 清空错误
error_reporter_.Clear();
// 初始化统计信息
stats_ = BuildStatistics{};
stats_.is_incremental = true;
stats_.total_symbols = parse_result.result.nodes.size();
// 创建收集上下文
CollectorContext context(registry_, error_reporter_);
// 创建增量收集器并执行
IncrementalCollector collector(context, *incremental_engine_);
bool success = collector.CollectIncremental(parse_result);
// 更新统计信息
stats_.reused_symbols = collector.GetReusedCount();
stats_.new_symbols = collector.GetNewCount();
// 修复:防止除零
if (stats_.total_symbols > 0)
{
stats_.reuse_rate = static_cast<double>(stats_.reused_symbols) / stats_.total_symbols;
}
else
{
stats_.reuse_rate = 0.0;
}
stats_.success = success && !error_reporter_.HasErrors();
// 检查缓存大小,必要时进行清理
if (incremental_engine_->GetCacheSize() > 10000) // 可配置
{
// LRU 会自动处理,这里只是检查
// 如果需要强制限制,可以调用 SetMaxCacheSize
}
return stats_.success;
}
// ==================== 访问器 ====================
const std::vector<Error>& SymbolTableBuilder::GetErrors() const
{
return error_reporter_.GetErrors();
}
bool SymbolTableBuilder::HasErrors() const
{
return error_reporter_.HasErrors();
}
size_t SymbolTableBuilder::ErrorCount() const
{
return error_reporter_.ErrorCount();
}
void SymbolTableBuilder::ClearErrors()
{
error_reporter_.Clear();
}
// ==================== 增量配置 ====================
void SymbolTableBuilder::EnableIncremental(bool enable)
{
incremental_enabled_ = enable;
if (enable && !incremental_engine_)
{
incremental_engine_ = std::make_unique<IncrementalEngine>();
}
}
void SymbolTableBuilder::SetMaxCacheSize(size_t max_size)
{
if (incremental_engine_)
{
incremental_engine_->SetMaxCacheSize(max_size);
}
}
void SymbolTableBuilder::ClearCache()
{
if (incremental_engine_)
{
incremental_engine_->Clear();
}
}
size_t SymbolTableBuilder::GetCacheSize() const
{
if (incremental_engine_)
{
return incremental_engine_->GetCacheSize();
}
return 0;
}
}
@@ -0,0 +1,105 @@
#pragma once
#include <vector>
#include <memory>
#include "../../ast/types.hpp"
#include "../../ast/deserializer.hpp"
#include "../core/registry.hpp"
#include "../core/error.hpp"
namespace lsp::language::symbol
{
// 前向声明
class IncrementalEngine;
// ==================== 构建统计信息 ====================
struct BuildStatistics
{
size_t total_symbols = 0; // 总符号数
size_t reused_symbols = 0; // 复用的符号数
size_t new_symbols = 0; // 新创建的符号数
double reuse_rate = 0.0; // 复用率
bool is_incremental = false; // 是否为增量构建
bool success = false; // 构建是否成功
};
// ==================== 符号表构建器 ====================
/**
* 符号表构建器 - 简化为调度器
*
* 职责:
* - 提供构建入口(完整/增量)
* - 管理核心组件(Registry、ErrorReporter
* - 管理增量引擎(可选)
* - 收集和提供统计信息
*
* 不负责:
* - 具体的符号收集逻辑(委托给 Collector)
* - 增量细节(委托给 IncrementalEngine
* - 语义分析(属于后续阶段)
*/
class SymbolTableBuilder
{
public:
SymbolTableBuilder();
~SymbolTableBuilder();
// 禁止拷贝
SymbolTableBuilder(const SymbolTableBuilder&) = delete;
SymbolTableBuilder& operator=(const SymbolTableBuilder&) = delete;
bool Build(const std::vector<ast::ASTNode>& nodes);
bool BuildIncremental(const ast::IncrementalParseResult& parse_result);
SymbolRegistry& GetRegistry() { return registry_; }
const SymbolRegistry& GetRegistry() const { return registry_; }
const std::vector<Error>& GetErrors() const;
bool HasErrors() const;
size_t ErrorCount() const;
void ClearErrors();
BuildStatistics GetStatistics() const { return stats_; }
void EnableIncremental(bool enable);
void SetMaxCacheSize(size_t max_size);
void ClearCache();
size_t GetCacheSize() const;
bool IsIncrementalEnabled() const { return incremental_enabled_; }
private:
// 核心组件
SymbolRegistry registry_;
ErrorReporter error_reporter_;
// 增量支持(可选)
std::unique_ptr<IncrementalEngine> incremental_engine_;
bool incremental_enabled_;
// 统计信息
BuildStatistics stats_;
};
// ==================== 便捷函数 ====================
/**
* 便捷函数:一次性构建符号表
*
* @param nodes AST节点列表
* @param errors 可选的错误输出参数
* @return 构建好的符号注册表(移动语义)
*/
inline SymbolRegistry BuildSymbolTable(const std::vector<ast::ASTNode>& nodes, std::vector<Error>* errors = nullptr)
{
SymbolTableBuilder builder;
builder.Build(nodes);
if (errors)
*errors = builder.GetErrors();
// 移动 Registry(避免拷贝)
return std::move(builder.GetRegistry());
}
}
@@ -0,0 +1,100 @@
#pragma once
#include <sstream>
#include "../core/registry.hpp"
#include "../core/error.hpp"
#include "../factory/scope_manager.hpp"
namespace lsp::language::symbol
{
/**
* 收集上下文 - 封装收集过程中的共享状态
*
* 职责:
* - 提供对 Registry、ErrorReporter、ScopeManager 的统一访问
* - 维护当前上下文(当前 Unit、当前 Class)
* - 提供便捷的错误报告接口
*/
struct CollectorContext
{
SymbolRegistry& registry;
ErrorReporter& error_reporter;
ScopeManager scope_manager;
// 当前上下文
Unit* current_unit = nullptr;
Class* current_class = nullptr;
CollectorContext(SymbolRegistry& reg, ErrorReporter& reporter) :
registry(reg), error_reporter(reporter), scope_manager(reg.GlobalScope())
{
}
// 便捷访问
Table* CurrentScope() { return scope_manager.Current(); }
Table* GlobalScope() { return registry.GlobalScope(); }
// ==================== 改进的错误报告 ====================
void ReportError(ErrorKind kind, const std::string& msg, const ast::Location& loc)
{
error_reporter.Report(kind, msg, loc);
}
void ReportDuplicateDefinition(const std::string& name, const ast::Location& loc)
{
// 查找已存在的符号位置
auto existing = CurrentScope()->LookupLocal(name);
if (existing && existing.symbol)
{
std::ostringstream msg;
msg << "Symbol '" << name << "' already defined at "
<< existing.symbol->location.start_line << ":"
<< existing.symbol->location.start_column;
error_reporter.Report(ErrorKind::kDuplicateDefinition, msg.str(), loc);
}
else
{
error_reporter.ReportDuplicateDefinition(name, loc);
}
}
void ReportSignatureConflict(const std::string& name, const ast::Location& loc)
{
// 查找冲突的函数重载
auto overloads = CurrentScope()->LookupOverloads(name);
if (!overloads.empty())
{
std::ostringstream msg;
msg << "Function signature conflict: '" << name
<< "' (conflicts with overload at "
<< overloads[0]->location.start_line << ":"
<< overloads[0]->location.start_column << ")";
error_reporter.Report(ErrorKind::kSignatureConflict, msg.str(), loc);
}
else
{
error_reporter.Report(ErrorKind::kSignatureConflict,
"Function signature conflict: " + name,
loc);
}
}
void ReportUnitConflict(const std::string& name, const ast::Location& loc)
{
auto existing_unit = registry.FindUnit(name);
if (existing_unit)
{
std::ostringstream msg;
msg << "Unit '" << name << "' already defined at "
<< existing_unit->location.start_line << ":"
<< existing_unit->location.start_column;
error_reporter.Report(ErrorKind::kDuplicateDefinition, msg.str(), loc);
}
else
{
error_reporter.ReportDuplicateDefinition(name, loc);
}
}
};
}
@@ -0,0 +1,87 @@
#include "./incremental_collector.hpp"
#include "../incremental/incremental_engine.hpp"
namespace lsp::language::symbol
{
IncrementalCollector::IncrementalCollector(CollectorContext& context, IncrementalEngine& engine) :
SymbolCollector(context), engine_(engine)
{
}
bool IncrementalCollector::CollectIncremental(const ast::IncrementalParseResult& parse_result)
{
// 重置统计
reused_count_ = 0;
new_count_ = 0;
// 构建变化节点索引
std::unordered_set<size_t> changed_set(
parse_result.changed_indices.begin(),
parse_result.changed_indices.end());
// 处理所有节点
for (size_t i = 0; i < parse_result.result.nodes.size(); ++i)
{
const auto& node = parse_result.result.nodes[i];
bool is_changed = changed_set.count(i) > 0;
if (!ProcessNode(node, is_changed))
return false;
}
return !ctx_.error_reporter.HasErrors();
}
bool IncrementalCollector::ProcessNode(const ast::ASTNode& node, bool is_changed)
{
if (is_changed)
{
// 节点已变化,必须重新收集
new_count_++;
bool success = Visit(node);
if (success)
{
// 收集成功后,缓存新符号
CacheCurrentSymbol(node);
}
return success;
}
else
{
// 节点未变化,尝试复用缓存
if (TryReuseFromCache(node))
{
reused_count_++;
return true;
}
else
{
// 缓存未命中,重新收集
new_count_++;
bool success = Visit(node);
if (success)
{
CacheCurrentSymbol(node);
}
return success;
}
}
}
bool IncrementalCollector::TryReuseFromCache(const ast::ASTNode& node)
{
// 委托给增量引擎,传入 Registry 用于 Unit 复用
return engine_.TryReuseSymbol(node, ctx_.CurrentScope(), &ctx_.registry);
}
void IncrementalCollector::CacheCurrentSymbol(const ast::ASTNode& node)
{
// 委托给增量引擎
engine_.CacheSymbol(node, ctx_.CurrentScope());
}
}
@@ -0,0 +1,47 @@
#pragma once
#include "./symbol_collector.hpp"
#include "../../ast/deserializer.hpp"
namespace lsp::language::symbol
{
// 前向声明
class IncrementalEngine;
/**
* 增量符号收集器
*
* 职责:
* - 继承基础收集器的所有能力
* - 根据节点是否变化决定复用或重新收集
* - 委托 IncrementalEngine 进行缓存操作
* - 收集统计信息
*/
class IncrementalCollector : public SymbolCollector
{
public:
IncrementalCollector(CollectorContext& context, IncrementalEngine& engine);
// 增量收集入口
bool CollectIncremental(const ast::IncrementalParseResult& parse_result);
// 统计信息
size_t GetReusedCount() const { return reused_count_; }
size_t GetNewCount() const { return new_count_; }
private:
// 处理单个节点(判断是复用还是重新收集)
bool ProcessNode(const ast::ASTNode& node, bool is_changed);
// 尝试从缓存复用符号
bool TryReuseFromCache(const ast::ASTNode& node);
// 缓存当前收集的符号
void CacheCurrentSymbol(const ast::ASTNode& node);
private:
IncrementalEngine& engine_;
size_t reused_count_ = 0;
size_t new_count_ = 0;
};
}
@@ -0,0 +1,518 @@
#include "./symbol_collector.hpp"
#include "../utils/type.hpp"
#include "../factory/factory.hpp"
namespace lsp::language::symbol
{
SymbolCollector::SymbolCollector(CollectorContext& context) :
ctx_(context)
{
}
bool SymbolCollector::Collect(const std::vector<ast::ASTNode>& nodes)
{
for (const auto& node : nodes)
{
if (!Visit(node))
return false;
}
return !ctx_.error_reporter.HasErrors();
}
// ==================== AST 访问 ====================
bool SymbolCollector::Visit(const ast::ASTNode& node)
{
if (std::holds_alternative<std::monostate>(node))
return true;
if (auto* unit = std::get_if<ast::UnitDefinition>(&node))
return CollectUnit(*unit);
if (auto* global = std::get_if<ast::GlobalDeclaration>(&node))
return CollectGlobal(*global);
if (auto* static_decl = std::get_if<ast::StaticDeclaration>(&node))
return CollectStatic(*static_decl);
if (auto* var = std::get_if<ast::VarDeclaration>(&node))
return CollectVariable(*var);
if (auto* constant = std::get_if<ast::ConstDeclaration>(&node))
return CollectConstant(*constant);
if (auto* stmt = std::get_if<ast::AssignmentStatement>(&node))
return CollectAssignment(*stmt);
if (auto* func_def = std::get_if<ast::FunctionDefinition>(&node))
return CollectFunctionDef(*func_def);
if (auto* cls = std::get_if<ast::ClassDefinition>(&node))
return CollectClass(*cls);
if (auto* uses = std::get_if<ast::UsesClause>(&node))
return CollectUsesClause(*uses);
// 跳过表达式和块
if (std::holds_alternative<ast::Expression>(node) ||
std::holds_alternative<ast::Block>(node))
return true;
return true;
}
// ==================== 收集方法 ====================
bool SymbolCollector::CollectUnit(const ast::UnitDefinition& unit)
{
auto unit_symbol = factory::CreateUnit(unit.name, unit.location);
if (!TryInsertUnit(unit_symbol))
return false;
ctx_.current_unit = unit_symbol.get();
// 创建 interface 和 implementation 作用域
unit_symbol->interface_symbols =
std::make_unique<Table>(ScopeKind::kInterface, ctx_.GlobalScope());
unit_symbol->implementation_symbols =
std::make_unique<Table>(ScopeKind::kImplementation, ctx_.GlobalScope());
// 收集 uses 子句
if (unit.uses)
CollectUsesClause(*unit.uses);
// 收集各部分的声明
CollectInScope(unit_symbol->interface_symbols.get(), unit.interface_statements);
CollectInScope(unit_symbol->implementation_symbols.get(), unit.implementation_statements);
CollectInScope(unit_symbol->implementation_symbols.get(), unit.initialization_statements);
CollectInScope(unit_symbol->implementation_symbols.get(), unit.finalization_statements);
ctx_.current_unit = nullptr;
return true;
}
bool SymbolCollector::CollectGlobal(const ast::GlobalDeclaration& global)
{
TypeInfo type = global.type_name ?
TypeFactory::FromAnnotation(*global.type_name) :
TypeInfo();
auto var_symbol = factory::CreateVariable(
global.name, Kind::kGlobalVariable, global.location, type);
if (global.value)
var_symbol->initialization_expr = global.value->text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectStatic(const ast::StaticDeclaration& decl)
{
TypeInfo type = decl.type_name ?
TypeFactory::FromAnnotation(*decl.type_name) :
TypeInfo();
auto var_symbol = factory::CreateVariable(
decl.name, Kind::kStaticVariable, decl.location, type);
var_symbol->attributes.is_static = true;
if (decl.value)
var_symbol->initialization_expr = decl.value->text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectVariable(const ast::VarDeclaration& var)
{
TypeInfo type = var.type_name ?
TypeFactory::FromAnnotation(*var.type_name) :
TypeInfo();
auto var_symbol = factory::CreateVariable(
var.name, Kind::kVariable, var.location, type);
if (var.value)
var_symbol->initialization_expr = var.value->text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectConstant(const ast::ConstDeclaration& constant)
{
TypeInfo type = constant.type_name ?
TypeFactory::FromAnnotation(*constant.type_name) :
TypeInfo();
auto const_symbol = factory::CreateConstant(
constant.name, constant.location, type, constant.value.text);
return TryInsert(const_symbol);
}
bool SymbolCollector::CollectAssignment(const ast::AssignmentStatement& stmt)
{
TypeInfo type;
auto var_symbol = factory::CreateVariable(
stmt.name, Kind::kVariable, stmt.location, type);
var_symbol->initialization_expr = stmt.value.text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectFunctionDef(const ast::FunctionDefinition& func)
{
Signature sig = CreateSignature(func.signature);
auto func_symbol = factory::CreateFunction(
func.name, func.location, sig);
if (!TryInsertFunction(func_symbol, func.location))
return false;
// 收集函数体
if (!func.body.statements.empty())
CollectFunctionBody(func_symbol.get(), func.body);
return true;
}
bool SymbolCollector::CollectClass(const ast::ClassDefinition& class_def)
{
auto class_symbol = factory::CreateClass(
class_def.name, class_def.location);
// 存储父类名称(字符串形式,不解析引用)
class_symbol->parent_names = class_def.parents;
if (!TryInsert(class_symbol))
return false;
// 创建成员作用域
class_symbol->members = std::make_unique<Table>(
ScopeKind::kClass, ctx_.CurrentScope());
ctx_.current_class = class_symbol.get();
// 进入类作用域,收集成员
auto guard = ctx_.scope_manager.EnterScope(class_symbol->members.get());
for (const auto& member : class_def.members)
{
CollectClassMember(member, class_symbol.get());
}
ctx_.current_class = nullptr;
return true;
}
bool SymbolCollector::CollectUsesClause(const ast::UsesClause& uses)
{
if (ctx_.current_unit)
ctx_.current_unit->uses = uses.units;
return true;
}
// ==================== 类成员收集 ====================
bool SymbolCollector::CollectClassMember(const ast::ClassMember& member, Class* owner)
{
if (std::holds_alternative<std::monostate>(member.content))
return true;
Access access = member.access;
if (auto* var = std::get_if<ast::VarDeclaration>(&member.content))
return CollectMemberVariable(*var, access);
if (auto* static_decl = std::get_if<ast::StaticDeclaration>(&member.content))
return CollectMemberStatic(*static_decl, access);
if (auto* method = std::get_if<ast::Method>(&member.content))
return CollectMemberMethod(*method, access, owner);
if (auto* property = std::get_if<ast::Property>(&member.content))
return CollectMemberProperty(*property, access);
if (auto* ctor = std::get_if<ast::ConstructorDeclaration>(&member.content))
return CollectMemberConstructor(*ctor, access, owner);
if (auto* dtor = std::get_if<ast::DestructorDeclaration>(&member.content))
return CollectMemberDestructor(*dtor, access, owner);
return true;
}
bool SymbolCollector::CollectMemberVariable(const ast::VarDeclaration& var, Access access)
{
TypeInfo type = var.type_name ?
TypeFactory::FromAnnotation(*var.type_name) :
TypeInfo();
auto var_symbol = factory::CreateVariable(
var.name, Kind::kVariable, var.location, type);
var_symbol->attributes.access = access;
if (var.value)
var_symbol->initialization_expr = var.value->text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectMemberStatic(const ast::StaticDeclaration& decl, Access access)
{
TypeInfo type = decl.type_name ?
TypeFactory::FromAnnotation(*decl.type_name) :
TypeInfo();
auto var_symbol = factory::CreateVariable(
decl.name, Kind::kStaticVariable, decl.location, type);
var_symbol->attributes.access = access;
var_symbol->attributes.is_static = true;
if (decl.value)
var_symbol->initialization_expr = decl.value->text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectMemberMethod(const ast::Method& method,
Access access,
Class* owner)
{
Signature sig = CreateSignature(method.signature);
auto method_symbol = factory::CreateMethod(
method.name, method.location, sig, owner);
method_symbol->attributes.access = access;
method_symbol->attributes.is_class_method = method.is_class_method;
// 设置 virtual/override 属性
switch (method.modifier)
{
case ast::Modifier::kVirtual:
method_symbol->attributes.is_virtual = true;
break;
case ast::Modifier::kOverride:
method_symbol->attributes.is_override = true;
break;
case ast::Modifier::kOverload:
method_symbol->attributes.is_overload = true;
break;
case ast::Modifier::kNone:
default:
break;
}
if (!TryInsertFunction(method_symbol, method.location))
return false;
// 收集方法体
if (method.body)
CollectFunctionBody(method_symbol.get(), *method.body);
return true;
}
bool SymbolCollector::CollectMemberProperty(const ast::Property& property, Access access)
{
TypeInfo type = property.type_name ?
TypeFactory::FromAnnotation(*property.type_name) :
TypeInfo();
auto property_symbol = factory::CreateProperty(
property.name, property.location, type);
property_symbol->attributes.access = access;
property_symbol->getter = property.getter;
property_symbol->setter = property.setter;
return TryInsert(property_symbol);
}
bool SymbolCollector::CollectMemberConstructor(const ast::ConstructorDeclaration& ctor,
Access access,
Class* owner)
{
Signature sig = CreateSignature(ctor.signature);
auto ctor_symbol = factory::CreateConstructor(
"Create", ctor.location, sig, owner);
ctor_symbol->attributes.access = access;
if (!TryInsert(ctor_symbol))
return false;
// 收集构造函数体
if (ctor.body)
CollectConstructorBody(ctor_symbol.get(), *ctor.body);
return true;
}
bool SymbolCollector::CollectMemberDestructor(const ast::DestructorDeclaration& dtor,
Access access,
Class* owner)
{
auto dtor_symbol = factory::CreateDestructor(
"Destroy", dtor.location, owner);
dtor_symbol->attributes.access = access;
if (!TryInsert(dtor_symbol))
return false;
// 收集析构函数体
if (dtor.body)
CollectDestructorBody(dtor_symbol.get(), *dtor.body);
return true;
}
// ==================== 函数体收集 ====================
void SymbolCollector::CollectFunctionBody(Function* func, const ast::Block& body)
{
// 创建函数作用域
func->body_scope = std::make_unique<Table>(
ScopeKind::kFunction, ctx_.CurrentScope());
// 进入函数作用域
auto guard = ctx_.scope_manager.EnterScope(func->body_scope.get());
// 收集参数符号
CollectFunctionParams(func);
// 收集函数体中的局部声明
CollectStatements(body.statements);
}
void SymbolCollector::CollectFunctionParams(Function* func)
{
for (const auto& param : func->signature.parameters)
{
auto param_symbol = factory::CreateVariable(
param.name, Kind::kParameter, func->location, param.type);
param_symbol->attributes.is_var_param = param.is_var;
param_symbol->attributes.is_out_param = param.is_out;
func->body_scope->Insert(param_symbol);
}
}
void SymbolCollector::CollectConstructorBody(Constructor* ctor, const ast::Block& body)
{
ctor->body_scope = std::make_unique<Table>(
ScopeKind::kFunction, ctx_.CurrentScope());
auto guard = ctx_.scope_manager.EnterScope(ctor->body_scope.get());
// 收集参数
for (const auto& param : ctor->signature.parameters)
{
auto param_symbol = factory::CreateVariable(
param.name, Kind::kParameter, ctor->location, param.type);
param_symbol->attributes.is_var_param = param.is_var;
param_symbol->attributes.is_out_param = param.is_out;
ctor->body_scope->Insert(param_symbol);
}
CollectStatements(body.statements);
}
void SymbolCollector::CollectDestructorBody(Destructor* dtor, const ast::Block& body)
{
dtor->body_scope = std::make_unique<Table>(
ScopeKind::kFunction, ctx_.CurrentScope());
auto guard = ctx_.scope_manager.EnterScope(dtor->body_scope.get());
CollectStatements(body.statements);
}
// ==================== 辅助方法 ====================
void SymbolCollector::CollectInScope(Table* scope,
const std::vector<ast::ASTNode>& statements)
{
auto guard = ctx_.scope_manager.EnterScope(scope);
CollectStatements(statements);
}
void SymbolCollector::CollectStatements(const std::vector<ast::ASTNode>& statements)
{
for (const auto& stmt : statements)
Visit(stmt);
}
// ==================== 插入方法 ====================
bool SymbolCollector::TryInsert(SymbolPtr symbol)
{
if (!ctx_.CurrentScope()->Insert(symbol))
{
ctx_.ReportDuplicateDefinition(symbol->name, symbol->location);
return false;
}
return true;
}
bool SymbolCollector::TryInsertFunction(FunctionPtr func, const ast::Location& loc)
{
if (!ctx_.CurrentScope()->InsertFunction(func))
{
ctx_.ReportSignatureConflict(func->name, loc);
return false;
}
return true;
}
bool SymbolCollector::TryInsertUnit(UnitPtr unit)
{
if (!ctx_.registry.AddUnit(unit))
{
ctx_.ReportUnitConflict(unit->name, unit->location);
return false;
}
return true;
}
// ==================== 创建签名 ====================
Signature SymbolCollector::CreateSignature(const ast::Signature& ast_sig)
{
Signature sig;
for (const auto& ast_param : ast_sig.parameters)
{
sig.parameters.push_back(CreateParameter(ast_param));
}
if (ast_sig.return_type)
sig.return_type = TypeFactory::FromAnnotation(*ast_sig.return_type);
return sig;
}
Signature::Param SymbolCollector::CreateParameter(const ast::Parameter& ast_param)
{
Signature::Param param;
param.name = ast_param.name;
param.type = ast_param.type_name ?
TypeFactory::FromAnnotation(*ast_param.type_name) :
TypeInfo();
param.is_var = ast_param.is_var;
param.is_out = ast_param.is_out;
param.default_value = ast_param.default_value;
return param;
}
}
@@ -0,0 +1,86 @@
#pragma once
#include <vector>
#include "../../ast/types.hpp"
#include "./context.hpp"
namespace lsp::language::symbol
{
/**
* 符号收集器 - 负责从 AST 收集符号
*
* 职责:
* - 遍历 AST 节点
* - 创建符号对象
* - 插入作用域
* - 管理作用域切换
*
* 不负责:
* - 增量构建逻辑
* - 缓存管理
* - 依赖追踪
* - 类型引用解析(保持字符串形式)
*/
class SymbolCollector
{
public:
explicit SymbolCollector(CollectorContext& context);
virtual ~SymbolCollector() = default;
// 主入口 - 收集所有节点
bool Collect(const std::vector<ast::ASTNode>& nodes);
protected:
// ==================== AST 访问 ====================
virtual bool Visit(const ast::ASTNode& node);
// ==================== 顶层声明 ====================
bool CollectUnit(const ast::UnitDefinition& unit);
bool CollectGlobal(const ast::GlobalDeclaration& global);
bool CollectStatic(const ast::StaticDeclaration& decl);
bool CollectVariable(const ast::VarDeclaration& var);
bool CollectConstant(const ast::ConstDeclaration& constant);
bool CollectAssignment(const ast::AssignmentStatement& stmt);
bool CollectFunctionDef(const ast::FunctionDefinition& func);
bool CollectClass(const ast::ClassDefinition& class_def);
bool CollectUsesClause(const ast::UsesClause& uses);
// ==================== 类成员收集 ====================
bool CollectClassMember(const ast::ClassMember& member, Class* owner);
bool CollectMemberVariable(const ast::VarDeclaration& var, Access access);
bool CollectMemberStatic(const ast::StaticDeclaration& decl, Access access);
bool CollectMemberMethod(const ast::Method& method, Access access, Class* owner);
bool CollectMemberProperty(const ast::Property& property, Access access);
bool CollectMemberConstructor(const ast::ConstructorDeclaration& ctor, Access access, Class* owner);
bool CollectMemberDestructor(const ast::DestructorDeclaration& dtor, Access access, Class* owner);
// ==================== 函数体收集 ====================
void CollectFunctionBody(Function* func, const ast::Block& body);
void CollectFunctionParams(Function* func);
void CollectConstructorBody(Constructor* ctor, const ast::Block& body);
void CollectDestructorBody(Destructor* dtor, const ast::Block& body);
// ==================== 辅助方法 ====================
void CollectInScope(Table* scope, const std::vector<ast::ASTNode>& statements);
void CollectStatements(const std::vector<ast::ASTNode>& statements);
// ==================== 插入方法 ====================
bool TryInsert(SymbolPtr symbol);
bool TryInsertFunction(FunctionPtr func, const ast::Location& loc);
bool TryInsertUnit(UnitPtr unit);
// ==================== 创建签名 ====================
Signature CreateSignature(const ast::Signature& ast_sig);
Signature::Param CreateParameter(const ast::Parameter& ast_param);
protected:
CollectorContext& ctx_;
};
}
@@ -0,0 +1,108 @@
#include <sstream>
#include <unordered_map>
#include "./error.hpp"
namespace lsp::language::symbol
{
// ==================== 错误类型名称映射 ====================
namespace
{
const char* GetErrorKindName(ErrorKind kind)
{
static const std::unordered_map<ErrorKind, const char*> names = {
{ ErrorKind::kDuplicateDefinition, "Duplicate definition" },
{ ErrorKind::kSignatureConflict, "Signature conflict" },
{ ErrorKind::kUndefinedType, "Undefined type" },
{ ErrorKind::kInvalidAccess, "Invalid access" },
{ ErrorKind::kCircularDependency, "Circular dependency" },
{ ErrorKind::kInvalidOverride, "Invalid override" },
{ ErrorKind::kInvalidTypeReference, "Invalid type reference" },
{ ErrorKind::kMemberNotFound, "Member not found" },
{ ErrorKind::kInvalidModifier, "Invalid modifier" },
{ ErrorKind::kInvalidParent, "Invalid parent" },
};
auto it = names.find(kind);
return it != names.end() ? it->second : "Unknown error";
}
}
// ==================== Error 实现 ====================
Error::Error(ErrorKind k, const std::string& msg, const ast::Location& loc) :
kind(k), message(msg), location(loc)
{
}
std::string Error::ToString() const
{
std::ostringstream oss;
oss << "[" << location.start_line << ":" << location.start_column << "] ";
oss << GetErrorKindName(kind);
oss << ": " << message;
return oss.str();
}
Error Error::DuplicateDefinition(const std::string& name, const ast::Location& loc)
{
return Error(ErrorKind::kDuplicateDefinition, "Duplicate definition: " + name, loc);
}
Error Error::UndefinedType(const std::string& type, const ast::Location& loc)
{
return Error(ErrorKind::kUndefinedType, "Undefined type: " + type, loc);
}
Error Error::CircularDependency(const std::string& msg, const ast::Location& loc)
{
return Error(ErrorKind::kCircularDependency, msg, loc);
}
// ==================== ErrorReporter 实现 ====================
void ErrorReporter::Report(ErrorKind kind, const std::string& msg, const ast::Location& loc)
{
errors_.emplace_back(kind, msg, loc);
}
void ErrorReporter::Report(const Error& error)
{
errors_.push_back(error);
}
const std::vector<Error>& ErrorReporter::GetErrors() const
{
return errors_;
}
bool ErrorReporter::HasErrors() const
{
return !errors_.empty();
}
size_t ErrorReporter::ErrorCount() const
{
return errors_.size();
}
void ErrorReporter::Clear()
{
errors_.clear();
}
void ErrorReporter::ReportDuplicateDefinition(const std::string& name, const ast::Location& loc)
{
Report(Error::DuplicateDefinition(name, loc));
}
void ErrorReporter::ReportUndefinedType(const std::string& type, const ast::Location& loc)
{
Report(Error::UndefinedType(type, loc));
}
void ErrorReporter::ReportCircularDependency(const std::string& msg, const ast::Location& loc)
{
Report(Error::CircularDependency(msg, loc));
}
}
@@ -0,0 +1,56 @@
#pragma once
#include <string>
#include "../../ast/types.hpp"
namespace lsp::language::symbol
{
enum class ErrorKind
{
kDuplicateDefinition,
kSignatureConflict,
kUndefinedType,
kInvalidAccess,
kCircularDependency,
kInvalidOverride,
kInvalidTypeReference,
kMemberNotFound,
kInvalidModifier,
kInvalidParent,
};
struct Error
{
ErrorKind kind;
std::string message;
ast::Location location;
Error(ErrorKind k, const std::string& msg, const ast::Location& loc);
std::string ToString() const;
static Error DuplicateDefinition(const std::string& name, const ast::Location& loc);
static Error UndefinedType(const std::string& type, const ast::Location& loc);
static Error CircularDependency(const std::string& msg, const ast::Location& loc);
};
class ErrorReporter
{
public:
ErrorReporter() = default;
void Report(ErrorKind kind, const std::string& msg, const ast::Location& loc);
void Report(const Error& error);
const std::vector<Error>& GetErrors() const;
bool HasErrors() const;
size_t ErrorCount() const;
void Clear();
void ReportDuplicateDefinition(const std::string& name, const ast::Location& loc);
void ReportUndefinedType(const std::string& type, const ast::Location& loc);
void ReportCircularDependency(const std::string& msg, const ast::Location& loc);
private:
std::vector<Error> errors_;
};
}
@@ -0,0 +1,100 @@
#include "./registry.hpp"
namespace lsp::language::symbol
{
SymbolRegistry::SymbolRegistry() :
global_scope_(ScopeKind::kGlobal, nullptr)
{
}
// 移动构造函数
SymbolRegistry::SymbolRegistry(SymbolRegistry&& other) noexcept :
global_scope_(std::move(other.global_scope_)),
units_(std::move(other.units_))
{
// 修复 global_scope_ 中所有符号的 scope 指针
for (auto& [name, symbol] : global_scope_.Symbols())
{
if (symbol && symbol->scope == &other.global_scope_)
{
symbol->scope = &global_scope_;
}
}
// 修复 units_ 中所有符号的 scope 指针
for (auto& [name, unit] : units_)
{
if (unit && unit->scope == &other.global_scope_)
{
unit->scope = &global_scope_;
}
}
}
// 移动赋值运算符
SymbolRegistry& SymbolRegistry::operator=(SymbolRegistry&& other) noexcept
{
if (this != &other)
{
global_scope_ = std::move(other.global_scope_);
units_ = std::move(other.units_);
// 修复 global_scope_ 中所有符号的 scope 指针
for (auto& [name, symbol] : global_scope_.Symbols())
{
if (symbol && symbol->scope == &other.global_scope_)
{
symbol->scope = &global_scope_;
}
}
// 修复 units_ 中所有符号的 scope 指针
for (auto& [name, unit] : units_)
{
if (unit && unit->scope == &other.global_scope_)
{
unit->scope = &global_scope_;
}
}
}
return *this;
}
Table* SymbolRegistry::GlobalScope()
{
return &global_scope_;
}
const Table* SymbolRegistry::GlobalScope() const
{
return &global_scope_;
}
bool SymbolRegistry::AddUnit(UnitPtr unit)
{
if (!unit)
return false;
if (units_.count(unit->name) > 0)
return false;
if (!global_scope_.Insert(unit))
return false;
units_[unit->name] = unit;
return true;
}
UnitPtr SymbolRegistry::FindUnit(const std::string& name) const
{
auto it = units_.find(name);
if (it != units_.end())
return it->second;
return nullptr;
}
const std::unordered_map<std::string, UnitPtr>& SymbolRegistry::Units() const
{
return units_;
}
}
@@ -0,0 +1,37 @@
#pragma once
#include <unordered_map>
#include "./symbol.hpp"
#include "./table.hpp"
namespace lsp::language::symbol
{
class SymbolRegistry
{
public:
SymbolRegistry();
~SymbolRegistry() = default;
SymbolRegistry(const SymbolRegistry&) = delete;
SymbolRegistry& operator=(const SymbolRegistry&) = delete;
// 自定义移动构造和移动赋值
SymbolRegistry(SymbolRegistry&& other) noexcept;
SymbolRegistry& operator=(SymbolRegistry&& other) noexcept;
// ==================== 访问全局作用域 ====================
Table* GlobalScope();
const Table* GlobalScope() const;
// ==================== Unit 管理 ====================
bool AddUnit(UnitPtr unit);
UnitPtr FindUnit(const std::string& name) const;
const std::unordered_map<std::string, UnitPtr>& Units() const;
private:
Table global_scope_;
std::unordered_map<std::string, UnitPtr> units_;
};
}
@@ -0,0 +1,78 @@
#include "./symbol.hpp"
#include "./table.hpp"
namespace lsp::language::symbol
{
// ==================== Function 实现 ====================
Function::Function(const std::string& name, const ast::Location& loc, const Signature& sig) :
Symbol(name, Kind::kFunction, loc), signature(sig), is_overload(false), body_scope(nullptr)
{
}
Function::~Function() = default;
Function::Function(Function&&) noexcept = default;
Function& Function::operator=(Function&&) noexcept = default;
// ==================== Method 实现 ====================
Method::Method(const std::string& name, const ast::Location& loc, const Signature& sig) :
Function(name, loc, sig), owner_class(nullptr)
{
kind = Kind::kMethod;
}
// ==================== Constructor 实现 ====================
Constructor::Constructor(const std::string& name, const ast::Location& loc, const Signature& sig) :
Symbol(name, Kind::kConstructor, loc), signature(sig), owner_class(nullptr), body_scope(nullptr)
{
}
Constructor::~Constructor() = default;
Constructor::Constructor(Constructor&&) noexcept = default;
Constructor& Constructor::operator=(Constructor&&) noexcept = default;
// ==================== Destructor 实现 ====================
Destructor::Destructor(const std::string& name, const ast::Location& loc) :
Symbol(name, Kind::kDestructor, loc), owner_class(nullptr), body_scope(nullptr)
{
}
Destructor::~Destructor() = default;
Destructor::Destructor(Destructor&&) noexcept = default;
Destructor& Destructor::operator=(Destructor&&) noexcept = default;
// ==================== Class 实现 ====================
Class::Class(const std::string& name, const ast::Location& loc) :
Symbol(name, Kind::kClass, loc), members(nullptr)
{
}
Class::~Class() = default;
Class::Class(Class&&) noexcept = default;
Class& Class::operator=(Class&&) noexcept = default;
// ==================== Unit 实现 ====================
Unit::Unit(const std::string& name, const ast::Location& loc) :
Symbol(name, Kind::kUnit, loc), interface_symbols(nullptr), implementation_symbols(nullptr)
{
}
Unit::~Unit() = default;
Unit::Unit(Unit&&) noexcept = default;
Unit& Unit::operator=(Unit&&) noexcept = default;
}
@@ -0,0 +1,270 @@
#pragma once
#include <string>
#include <vector>
#include <optional>
#include <memory>
#include "../../ast/types.hpp"
namespace lsp::language::symbol
{
// 前向声明
class Table;
// ==================== 基本枚举 ====================
enum class Kind
{
kVariable,
kStaticVariable,
kGlobalVariable,
kConstant,
kParameter,
kFunction,
kClass,
kMethod,
kConstructor,
kDestructor,
kProperty,
kUnit,
};
enum class ScopeKind
{
kGlobal,
kUnit,
kInterface,
kImplementation,
kFunction,
kClass,
kBlock,
};
using Access = ast::Access;
// ==================== 符号属性 ====================
struct Attributes
{
bool is_const = false;
bool is_static = false;
bool is_var_param = false;
bool is_out_param = false;
Access access = Access::kPublic;
bool is_virtual = false;
bool is_override = false;
bool is_overload = false;
bool is_class_method = false;
};
// ==================== 类型信息(纯数据) ====================
class TypeInfo
{
public:
TypeInfo() = default;
explicit TypeInfo(const std::string& annotation) :
annotation_(annotation) {}
bool HasAnnotation() const { return !annotation_.empty(); }
const std::string& Annotation() const { return annotation_; }
// bool IsArray() const;
// bool IsPrimitive() const;
private:
std::string annotation_; // 类型注解(原始字符串)
};
// ==================== 函数签名(纯数据) ====================
class Signature
{
public:
size_t ParamCount() const { return parameters.size(); }
bool HasReturnType() const { return return_type.has_value(); }
public:
struct Param
{
std::string name;
TypeInfo type;
bool is_var = false;
bool is_out = false;
std::optional<std::string> default_value;
};
std::vector<Param> parameters;
std::optional<TypeInfo> return_type;
};
// ==================== 符号基类 ====================
class Symbol
{
public:
Symbol(const std::string& name, Kind kind, const ast::Location& loc) :
name(name), kind(kind), location(loc), scope(nullptr)
{
}
virtual ~Symbol() = default;
Symbol(const Symbol&) = delete;
Symbol& operator=(const Symbol&) = delete;
Symbol(Symbol&&) noexcept = default;
Symbol& operator=(Symbol&&) noexcept = default;
public:
std::string name;
Kind kind;
ast::Location location;
Table* scope;
Attributes attributes;
};
// ==================== 具体符号类 ====================
class Variable : public Symbol
{
public:
Variable(const std::string& name, Kind kind, const ast::Location& loc, const TypeInfo& type) :
Symbol(name, kind, loc), type(type)
{
}
public:
TypeInfo type;
std::optional<std::string> initialization_expr;
};
class Constant : public Symbol
{
public:
Constant(const std::string& name, const ast::Location& loc, const TypeInfo& type, const std::string& value) :
Symbol(name, Kind::kConstant, loc), type(type), value(value)
{
attributes.is_const = true;
}
public:
TypeInfo type;
std::string value;
};
class Function : public Symbol
{
public:
Function(const std::string& name, const ast::Location& loc, const Signature& sig);
~Function() override;
Function(const Function&) = delete;
Function& operator=(const Function&) = delete;
Function(Function&&) noexcept;
Function& operator=(Function&&) noexcept;
public:
Signature signature;
bool is_overload;
std::unique_ptr<Table> body_scope;
};
class Method : public Function
{
public:
Method(const std::string& name, const ast::Location& loc, const Signature& sig);
public:
class Class* owner_class;
std::optional<ast::Location> implementation_location;
};
class Constructor : public Symbol
{
public:
Signature signature;
class Class* owner_class;
std::unique_ptr<Table> body_scope;
Constructor(const std::string& name, const ast::Location& loc, const Signature& sig);
~Constructor() override;
Constructor(const Constructor&) = delete;
Constructor& operator=(const Constructor&) = delete;
Constructor(Constructor&&) noexcept;
Constructor& operator=(Constructor&&) noexcept;
};
class Destructor : public Symbol
{
public:
class Class* owner_class;
std::unique_ptr<Table> body_scope;
Destructor(const std::string& name, const ast::Location& loc);
~Destructor() override;
Destructor(const Destructor&) = delete;
Destructor& operator=(const Destructor&) = delete;
Destructor(Destructor&&) noexcept;
Destructor& operator=(Destructor&&) noexcept;
};
class Property : public Symbol
{
public:
TypeInfo type;
std::optional<std::string> getter;
std::optional<std::string> setter;
Property(const std::string& name, const ast::Location& loc, const TypeInfo& type) :
Symbol(name, Kind::kProperty, loc), type(type)
{
}
};
class Class : public Symbol
{
public:
std::vector<std::string> parent_names;
std::vector<Class*> parents;
std::unique_ptr<Table> members;
Class(const std::string& name, const ast::Location& loc);
~Class() override;
Class(const Class&) = delete;
Class& operator=(const Class&) = delete;
Class(Class&&) noexcept;
Class& operator=(Class&&) noexcept;
};
class Unit : public Symbol
{
public:
std::vector<std::string> uses;
std::unique_ptr<Table> interface_symbols;
std::unique_ptr<Table> implementation_symbols;
Unit(const std::string& name, const ast::Location& loc);
~Unit() override;
Unit(const Unit&) = delete;
Unit& operator=(const Unit&) = delete;
Unit(Unit&&) noexcept;
Unit& operator=(Unit&&) noexcept;
};
// ==================== 智能指针类型别名 ====================
using SymbolPtr = std::shared_ptr<Symbol>;
using VariablePtr = std::shared_ptr<Variable>;
using ConstantPtr = std::shared_ptr<Constant>;
using FunctionPtr = std::shared_ptr<Function>;
using MethodPtr = std::shared_ptr<Method>;
using ConstructorPtr = std::shared_ptr<Constructor>;
using DestructorPtr = std::shared_ptr<Destructor>;
using PropertyPtr = std::shared_ptr<Property>;
using ClassPtr = std::shared_ptr<Class>;
using UnitPtr = std::shared_ptr<Unit>;
}
@@ -0,0 +1,146 @@
#include "./table.hpp"
namespace lsp::language::symbol
{
// ==================== LookupResult 实现 ====================
LookupResult LookupResult::Found(Symbol* sym, Table* scp)
{
LookupResult result;
result.symbol = sym;
result.scope = scp;
result.success = true;
return result;
}
LookupResult LookupResult::NotFound()
{
return LookupResult{};
}
LookupResult::operator bool() const
{
return success;
}
// ==================== Table 实现 ====================
Table::Table(ScopeKind kind, Table* parent) :
kind_(kind), parent_(parent)
{
}
ScopeKind Table::Kind() const
{
return kind_;
}
Table* Table::Parent() const
{
return parent_;
}
const std::unordered_map<std::string, SymbolPtr>& Table::Symbols() const
{
return symbols_;
}
const std::unordered_map<std::string, std::vector<FunctionPtr>>& Table::OverloadedFunctions() const
{
return overloaded_functions_;
}
Table* Table::CreateChild(ScopeKind kind)
{
auto child = std::make_unique<Table>(kind, this);
Table* ptr = child.get();
children_.push_back(std::move(child));
return ptr;
}
bool Table::Insert(SymbolPtr symbol)
{
if (!symbol)
return false;
if (symbols_.count(symbol->name) > 0)
return false;
symbol->scope = this;
symbols_[symbol->name] = symbol;
return true;
}
bool Table::InsertFunction(FunctionPtr func)
{
if (!func)
return false;
func->scope = this;
auto& overloads = overloaded_functions_[func->name];
if (func->is_overload)
overloads.push_back(func);
if (overloads.size() == 1)
symbols_[func->name] = func;
return true;
}
LookupResult Table::LookupLocal(const std::string& name) const
{
auto it = symbols_.find(name);
if (it != symbols_.end())
return LookupResult::Found(it->second.get(), const_cast<Table*>(this));
return LookupResult::NotFound();
}
LookupResult Table::Lookup(const std::string& name) const
{
auto result = LookupLocal(name);
if (result)
return result;
if (parent_)
return parent_->Lookup(name);
return LookupResult::NotFound();
}
std::vector<FunctionPtr> Table::LookupOverloads(const std::string& name) const
{
auto it = overloaded_functions_.find(name);
if (it != overloaded_functions_.end())
return it->second;
if (parent_)
return parent_->LookupOverloads(name);
return {};
}
MethodPtr Table::FindMethodInClass(const std::string& class_name, const std::string& method_name) const
{
// 1. 查找类符号
auto class_result = Lookup(class_name);
if (!class_result || class_result.symbol->kind != Kind::kClass)
return nullptr;
auto class_sym = static_cast<Class*>(class_result.symbol);
if (!class_sym->members)
return nullptr;
auto method_result = class_sym->members->LookupLocal(method_name);
if (!method_result || method_result.symbol->kind != Kind::kMethod)
return nullptr;
auto it = class_sym->members->Symbols().find(method_name);
if (it != class_sym->members->Symbols().end())
return std::static_pointer_cast<Method>(it->second);
return nullptr;
}
}
@@ -0,0 +1,69 @@
#pragma once
#include <unordered_map>
#include <vector>
#include <memory>
#include "./symbol.hpp"
namespace lsp::language::symbol
{
// ==================== 查找结果 ====================
struct LookupResult
{
Symbol* symbol = nullptr;
Table* scope = nullptr;
bool success = false;
static LookupResult Found(Symbol* sym, Table* scp);
static LookupResult NotFound();
explicit operator bool() const;
};
// ==================== 符号表 / 作用域 ====================
class Table
{
public:
explicit Table(ScopeKind kind, Table* parent = nullptr);
~Table() = default;
Table(const Table&) = delete;
Table& operator=(const Table&) = delete;
Table(Table&&) noexcept = default;
Table& operator=(Table&&) noexcept = default;
// ==================== 访问器 ====================
ScopeKind Kind() const;
Table* Parent() const;
const std::unordered_map<std::string, SymbolPtr>& Symbols() const;
const std::unordered_map<std::string, std::vector<FunctionPtr>>& OverloadedFunctions() const;
// ==================== 作用域管理 ====================
Table* CreateChild(ScopeKind kind);
// ==================== 符号插入(核心方法) ====================
bool Insert(SymbolPtr symbol);
bool InsertFunction(FunctionPtr func);
// ==================== 符号查找 ====================
LookupResult LookupLocal(const std::string& name) const;
LookupResult Lookup(const std::string& name) const;
// 优化:返回 vector 引用或空 vector
std::vector<FunctionPtr> LookupOverloads(const std::string& name) const;
MethodPtr FindMethodInClass(const std::string& class_name, const std::string& method_name) const;
private:
ScopeKind kind_;
Table* parent_;
std::vector<std::unique_ptr<Table>> children_;
std::unordered_map<std::string, SymbolPtr> symbols_;
std::unordered_map<std::string, std::vector<FunctionPtr>> overloaded_functions_;
};
}
@@ -0,0 +1,114 @@
#include "../utils/type.hpp"
#include "./factory.hpp"
namespace lsp::language::symbol
{
// ==================== 创建符号对象 ====================
VariablePtr factory::CreateVariable(
const std::string& name,
Kind kind,
const ast::Location& loc,
const TypeInfo& type)
{
return std::make_shared<Variable>(name, kind, loc, type);
}
ConstantPtr factory::CreateConstant(
const std::string& name,
const ast::Location& loc,
const TypeInfo& type,
const std::string& value)
{
return std::make_shared<Constant>(name, loc, type, value);
}
FunctionPtr factory::CreateFunction(
const std::string& name,
const ast::Location& loc,
const Signature& sig)
{
return std::make_shared<Function>(name, loc, sig);
}
MethodPtr factory::CreateMethod(
const std::string& name,
const ast::Location& loc,
const Signature& sig,
Class* owner)
{
auto method = std::make_shared<Method>(name, loc, sig);
method->owner_class = owner;
return method;
}
ConstructorPtr factory::CreateConstructor(
const std::string& name,
const ast::Location& loc,
const Signature& sig,
Class* owner)
{
auto ctor = std::make_shared<Constructor>(name, loc, sig);
ctor->owner_class = owner;
return ctor;
}
DestructorPtr factory::CreateDestructor(
const std::string& name,
const ast::Location& loc,
Class* owner)
{
auto dtor = std::make_shared<Destructor>(name, loc);
dtor->owner_class = owner;
return dtor;
}
PropertyPtr factory::CreateProperty(
const std::string& name,
const ast::Location& loc,
const TypeInfo& type)
{
return std::make_shared<Property>(name, loc, type);
}
ClassPtr factory::CreateClass(
const std::string& name,
const ast::Location& loc)
{
return std::make_shared<Class>(name, loc);
}
UnitPtr factory::CreateUnit(
const std::string& name,
const ast::Location& loc)
{
return std::make_shared<Unit>(name, loc);
}
// ==================== 便捷方法 ====================
VariablePtr factory::CreateAndInsert(
Table* table,
const std::string& name,
Kind kind,
const ast::Location& loc,
const TypeInfo& type)
{
auto var = CreateVariable(name, kind, loc, type);
if (table && table->Insert(var))
return var;
return nullptr;
}
VariablePtr factory::CreateVariableFromAST(
const std::string& name,
Kind kind,
const ast::Location& loc,
const std::optional<std::string>& type_str)
{
TypeInfo type = type_str ?
TypeFactory::FromAnnotation(*type_str) :
TypeInfo();
return CreateVariable(name, kind, loc, type);
}
}
@@ -0,0 +1,110 @@
#pragma once
#include <optional>
#include "../../ast/types.hpp"
#include "../core/symbol.hpp"
#include "../core/table.hpp"
namespace lsp::language::symbol
{
/**
* 符号工厂 - 创建符号对象
*
* 职责:
* - 提供符号对象的创建接口
* - 封装 std::make_shared 调用
*
* 不负责:
* - AST 到 Symbol 的转换逻辑(属于 Collector
*/
namespace factory
{
// ==================== 创建符号对象 ====================
/**
* 创建变量符号
*/
VariablePtr CreateVariable(
const std::string& name,
Kind kind,
const ast::Location& loc,
const TypeInfo& type);
/**
* 创建常量符号
*/
ConstantPtr CreateConstant(
const std::string& name,
const ast::Location& loc,
const TypeInfo& type,
const std::string& value);
/**
* 创建函数符号
*/
FunctionPtr CreateFunction(
const std::string& name,
const ast::Location& loc,
const Signature& sig);
/**
* 创建方法符号
*/
MethodPtr CreateMethod(
const std::string& name,
const ast::Location& loc,
const Signature& sig,
Class* owner);
/**
* 创建构造函数符号
*/
ConstructorPtr CreateConstructor(
const std::string& name,
const ast::Location& loc,
const Signature& sig,
Class* owner);
/**
* 创建析构函数符号
*/
DestructorPtr CreateDestructor(
const std::string& name,
const ast::Location& loc,
Class* owner);
/**
* 创建属性符号
*/
PropertyPtr CreateProperty(
const std::string& name,
const ast::Location& loc,
const TypeInfo& type);
/**
* 创建类符号
*/
ClassPtr CreateClass(
const std::string& name,
const ast::Location& loc);
/**
* 创建 Unit 符号
*/
UnitPtr CreateUnit(const std::string& name, const ast::Location& loc);
// ==================== 便捷方法 ====================
/**
* 创建并插入变量
* @return 如果插入成功返回符号,否则返回 nullptr
*/
VariablePtr CreateAndInsert(Table* table, const std::string& name, Kind kind, const ast::Location& loc, const TypeInfo& type);
/**
* 从 AST 类型字符串创建变量
*/
VariablePtr CreateVariableFromAST(const std::string& name, Kind kind, const ast::Location& loc,
const std::optional<std::string>& type_str);
}
}
@@ -0,0 +1,74 @@
#include "./scope_manager.hpp"
namespace lsp::language::symbol
{
// ==================== ScopeGuard 实现 ====================
ScopeGuard::ScopeGuard(Table*& current, Table* new_scope) :
current_(current), previous_(current), active_(true)
{
current_ = new_scope;
}
ScopeGuard::~ScopeGuard()
{
if (active_)
{
current_ = previous_;
}
}
ScopeGuard::ScopeGuard(ScopeGuard&& other) noexcept :
current_(other.current_),
previous_(other.previous_),
active_(other.active_)
{
other.active_ = false;
}
ScopeGuard& ScopeGuard::operator=(ScopeGuard&& other) noexcept
{
if (this != &other)
{
if (active_)
{
current_ = previous_;
}
current_ = other.current_;
previous_ = other.previous_;
active_ = other.active_;
other.active_ = false;
}
return *this;
}
// ==================== ScopeManager 实现 ====================
ScopeManager::ScopeManager(Table* root) :
root_(root), current_(root)
{
}
Table* ScopeManager::Current() const
{
return current_;
}
ScopeGuard ScopeManager::EnterScope(Table* scope)
{
return ScopeGuard(current_, scope);
}
ScopeGuard ScopeManager::CreateAndEnterChild(ScopeKind kind)
{
Table* child = current_->CreateChild(kind);
return ScopeGuard(current_, child);
}
void ScopeManager::SetCurrent(Table* scope)
{
current_ = scope;
}
}
@@ -0,0 +1,53 @@
#pragma once
#include "../core/table.hpp"
namespace lsp::language::symbol
{
// ==================== 作用域守卫 ====================
// RAII风格的作用域管理
class ScopeGuard
{
public:
ScopeGuard(Table*& current, Table* new_scope);
~ScopeGuard();
ScopeGuard(const ScopeGuard&) = delete;
ScopeGuard& operator=(const ScopeGuard&) = delete;
ScopeGuard(ScopeGuard&& other) noexcept;
ScopeGuard& operator=(ScopeGuard&& other) noexcept;
private:
Table*& current_;
Table* previous_;
bool active_;
};
// ==================== 作用域管理器 ====================
// 负责管理当前作用域的切换和导航
class ScopeManager
{
public:
explicit ScopeManager(Table* root);
// 获取当前作用域
Table* Current() const;
// 进入指定作用域(返回守卫,自动恢复)
[[nodiscard]] ScopeGuard EnterScope(Table* scope);
// 创建子作用域并进入
[[nodiscard]] ScopeGuard CreateAndEnterChild(ScopeKind kind);
// 直接设置当前作用域(不推荐,破坏RAII)
void SetCurrent(Table* scope);
// 获取根作用域
Table* Root() const { return root_; }
private:
Table* root_;
Table* current_;
};
}
@@ -0,0 +1,145 @@
#include <sstream>
#include "./incremental.hpp"
namespace lsp::language::symbol
{
// ==================== SymbolCacheKey 实现 ====================
std::string SymbolCacheKey::ComputeSignatureHash(const Signature& sig)
{
std::ostringstream oss;
oss << sig.parameters.size() << "|";
for (const auto& param : sig.parameters)
{
oss << param.name << ":"
<< param.type.Annotation() << ":"
<< (param.is_var ? "v" : "")
<< (param.is_out ? "o" : "") << "|";
}
if (sig.return_type)
{
oss << "ret:" << sig.return_type->Annotation();
}
return oss.str();
}
// ==================== SymbolCache 实现 ====================
SymbolCache::SymbolCache(size_t max_size) :
max_size_(max_size)
{
}
const SymbolPtr* SymbolCache::Find(const SymbolCacheKey& key)
{
auto it = cache_.find(key);
if (it != cache_.end())
{
// 更新 LRU:移到最前面
TouchKey(key);
return &it->second.symbol;
}
return nullptr;
}
void SymbolCache::Insert(const SymbolCacheKey& key, const SymbolPtr& symbol)
{
// 检查是否已存在
auto it = cache_.find(key);
if (it != cache_.end())
{
// 更新现有条目
it->second.symbol = symbol;
TouchKey(key);
return;
}
// 检查是否需要淘汰
if (cache_.size() >= max_size_)
{
EvictLRU();
}
// 插入新条目
lru_list_.push_front(key);
cache_[key] = CacheEntry{ symbol, lru_list_.begin() };
}
void SymbolCache::Clear()
{
cache_.clear();
lru_list_.clear();
}
void SymbolCache::EvictLRU()
{
if (lru_list_.empty())
return;
// 删除最久未使用的项(列表末尾)
auto lru_key = lru_list_.back();
lru_list_.pop_back();
cache_.erase(lru_key);
}
void SymbolCache::TouchKey(const SymbolCacheKey& key)
{
auto it = cache_.find(key);
if (it == cache_.end())
return;
// 从当前位置删除
lru_list_.erase(it->second.lru_iter);
// 移到最前面
lru_list_.push_front(key);
it->second.lru_iter = lru_list_.begin();
}
SymbolCacheKey SymbolCache::MakeKey(const Symbol* symbol)
{
if (!symbol)
return SymbolCacheKey{};
SymbolCacheKey key;
key.symbol_name = symbol->name;
key.symbol_kind = symbol->kind;
key.declaration_line = symbol->location.start_line;
key.declaration_column = symbol->location.start_column;
// 对于函数,添加签名哈希
if (auto* func = dynamic_cast<const Function*>(symbol))
{
key.signature_hash = SymbolCacheKey::ComputeSignatureHash(func->signature);
}
else if (auto* ctor = dynamic_cast<const Constructor*>(symbol))
{
key.signature_hash = SymbolCacheKey::ComputeSignatureHash(ctor->signature);
}
return key;
}
SymbolCacheKey SymbolCache::MakeKeyFromAST(
const std::string& name,
Kind kind,
const ast::Location& name_location,
const std::optional<Signature>& signature)
{
SymbolCacheKey key;
key.symbol_name = name;
key.symbol_kind = kind;
key.declaration_line = name_location.start_line;
key.declaration_column = name_location.start_column;
if (signature)
{
key.signature_hash = SymbolCacheKey::ComputeSignatureHash(*signature);
}
return key;
}
}
@@ -0,0 +1,97 @@
#pragma once
#include <unordered_map>
#include <optional>
#include <list>
#include "../core/symbol.hpp"
namespace lsp::language::symbol
{
// ==================== 改进的缓存键设计 ====================
// 基于 AST 位置和内容,避免指针地址依赖
struct SymbolCacheKey
{
std::string symbol_name;
Kind symbol_kind;
uint32_t declaration_line; // 使用声明位置行号
uint32_t declaration_column; // 使用声明位置列号
std::optional<std::string> signature_hash; // 函数签名哈希
bool operator==(const SymbolCacheKey& other) const
{
return symbol_name == other.symbol_name &&
symbol_kind == other.symbol_kind &&
declaration_line == other.declaration_line &&
declaration_column == other.declaration_column &&
signature_hash == other.signature_hash;
}
// 生成签名哈希(用于函数/方法)
static std::string ComputeSignatureHash(const Signature& sig);
};
struct SymbolCacheKeyHash
{
size_t operator()(const SymbolCacheKey& key) const
{
size_t h1 = std::hash<std::string>()(key.symbol_name);
size_t h2 = std::hash<int>()(static_cast<int>(key.symbol_kind));
size_t h3 = std::hash<uint32_t>()(key.declaration_line);
size_t h4 = std::hash<uint32_t>()(key.declaration_column);
size_t h5 = key.signature_hash ?
std::hash<std::string>()(*key.signature_hash) :
0;
return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3) ^ (h5 << 4);
}
};
// ==================== 符号缓存管理器(带LRU ====================
class SymbolCache
{
public:
explicit SymbolCache(size_t max_size = 10000);
// 查找缓存
const SymbolPtr* Find(const SymbolCacheKey& key);
// 插入缓存
void Insert(const SymbolCacheKey& key, const SymbolPtr& symbol);
// 清空缓存
void Clear();
// 获取缓存大小
size_t Size() const { return cache_.size(); }
// 设置最大缓存大小
void SetMaxSize(size_t max_size) { max_size_ = max_size; }
// 从 Symbol 生成 Key
static SymbolCacheKey MakeKey(const Symbol* symbol);
// 从 AST 信息生成 Key
static SymbolCacheKey MakeKeyFromAST(
const std::string& name,
Kind kind,
const ast::Location& name_location,
const std::optional<Signature>& signature = std::nullopt);
private:
// LRU 淘汰策略
void EvictLRU();
void TouchKey(const SymbolCacheKey& key);
private:
struct CacheEntry
{
SymbolPtr symbol;
std::list<SymbolCacheKey>::iterator lru_iter;
};
std::unordered_map<SymbolCacheKey, CacheEntry, SymbolCacheKeyHash> cache_;
std::list<SymbolCacheKey> lru_list_; // 最近使用列表
size_t max_size_;
};
}
@@ -0,0 +1,344 @@
#include "../core/symbol.hpp"
#include "./incremental_engine.hpp"
namespace lsp::language::symbol
{
IncrementalEngine::IncrementalEngine() :
cache_(10000),
max_cache_size_(10000)
{
}
// ==================== 符号复用与缓存 ====================
bool IncrementalEngine::TryReuseSymbol(const ast::ASTNode& node, Table* scope, SymbolRegistry* registry)
{
return std::visit([this, scope, registry](auto&& arg) -> bool {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::monostate>)
{
return true;
}
else if constexpr (std::is_same_v<T, ast::VarDeclaration>)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kVariable, arg.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
return scope->Insert(*cached);
}
return false;
}
else if constexpr (std::is_same_v<T, ast::GlobalDeclaration>)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kGlobalVariable, arg.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
return scope->Insert(*cached);
}
return false;
}
else if constexpr (std::is_same_v<T, ast::StaticDeclaration>)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kStaticVariable, arg.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
return scope->Insert(*cached);
}
return false;
}
else if constexpr (std::is_same_v<T, ast::ConstDeclaration>)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kConstant, arg.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
return scope->Insert(*cached);
}
return false;
}
else if constexpr (std::is_same_v<T, ast::FunctionDefinition>)
{
// 创建签名用于缓存键
Signature sig;
for (const auto& param : arg.signature.parameters)
{
Signature::Param p;
p.name = param.name;
if (param.type_name)
{
p.type = TypeInfo(*param.type_name);
}
p.is_var = param.is_var;
p.is_out = param.is_out;
sig.parameters.push_back(p);
}
if (arg.signature.return_type)
{
sig.return_type = TypeInfo(*arg.signature.return_type);
}
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kFunction, arg.name_location, sig);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
auto func = std::dynamic_pointer_cast<Function>(*cached);
if (func)
{
return scope->InsertFunction(func);
}
}
return false;
}
else if constexpr (std::is_same_v<T, ast::ClassDefinition>)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kClass, arg.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
return scope->Insert(*cached);
}
return false;
}
else if constexpr (std::is_same_v<T, ast::UnitDefinition>)
{
// Unit 支持复用
if (registry)
{
return TryReuseUnit(arg, registry);
}
return false;
}
else
{
// 其他类型(Expression, Block 等)直接跳过
return true;
}
},
node);
}
bool IncrementalEngine::TryReuseUnit(
const ast::UnitDefinition& unit_ast,
SymbolRegistry* registry)
{
if (!registry)
return false;
auto key = SymbolCache::MakeKeyFromAST(
unit_ast.name, Kind::kUnit, unit_ast.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
auto unit = std::dynamic_pointer_cast<Unit>(*cached);
if (unit)
{
// 尝试将缓存的 Unit 添加到 Registry
return registry->AddUnit(unit);
}
}
return false;
}
void IncrementalEngine::CacheSymbol(const ast::ASTNode& node, Table* scope)
{
std::visit([this, scope](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, ast::VarDeclaration> ||
std::is_same_v<T, ast::GlobalDeclaration> ||
std::is_same_v<T, ast::StaticDeclaration>)
{
auto result = scope->LookupLocal(arg.name);
if (result && result.symbol)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, result.symbol->kind, arg.name_location);
const auto& symbols = scope->Symbols();
auto it = symbols.find(arg.name);
if (it != symbols.end())
{
cache_.Insert(key, it->second);
}
}
}
else if constexpr (std::is_same_v<T, ast::ConstDeclaration>)
{
auto result = scope->LookupLocal(arg.name);
if (result && result.symbol)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kConstant, arg.name_location);
const auto& symbols = scope->Symbols();
auto it = symbols.find(arg.name);
if (it != symbols.end())
{
cache_.Insert(key, it->second);
}
}
}
else if constexpr (std::is_same_v<T, ast::FunctionDefinition>)
{
auto result = scope->LookupLocal(arg.name);
if (result && result.symbol)
{
// 创建签名用于缓存键
Signature sig;
for (const auto& param : arg.signature.parameters)
{
Signature::Param p;
p.name = param.name;
if (param.type_name)
{
p.type = TypeInfo(*param.type_name);
}
p.is_var = param.is_var;
p.is_out = param.is_out;
sig.parameters.push_back(p);
}
if (arg.signature.return_type)
{
sig.return_type = TypeInfo(*arg.signature.return_type);
}
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kFunction, arg.name_location, sig);
const auto& symbols = scope->Symbols();
auto it = symbols.find(arg.name);
if (it != symbols.end())
{
cache_.Insert(key, it->second);
}
}
}
else if constexpr (std::is_same_v<T, ast::ClassDefinition>)
{
auto result = scope->LookupLocal(arg.name);
if (result && result.symbol)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kClass, arg.name_location);
const auto& symbols = scope->Symbols();
auto it = symbols.find(arg.name);
if (it != symbols.end())
{
cache_.Insert(key, it->second);
}
}
}
else if constexpr (std::is_same_v<T, ast::UnitDefinition>)
{
// Unit 缓存需要从 Registry 获取
// 这里暂时不处理,在 BuildCache 中统一处理
}
// 其他类型不需要缓存
},
node);
}
void IncrementalEngine::BuildCache(const SymbolRegistry& registry)
{
// 缓存所有 Unit
for (const auto& [name, unit] : registry.Units())
{
auto key = SymbolCache::MakeKey(unit.get());
cache_.Insert(key, unit);
// 递归缓存 Unit 内部的符号
if (unit->interface_symbols)
CacheScopeRecursive(unit->interface_symbols.get());
if (unit->implementation_symbols)
CacheScopeRecursive(unit->implementation_symbols.get());
}
// 缓存全局作用域
CacheScopeRecursive(const_cast<Table*>(registry.GlobalScope()));
}
void IncrementalEngine::CacheScopeRecursive(Table* scope)
{
if (!scope)
return;
// 缓存当前作用域的所有符号
for (const auto& [name, symbol] : scope->Symbols())
{
auto key = SymbolCache::MakeKey(symbol.get());
cache_.Insert(key, symbol);
// 递归缓存类成员
if (auto* cls = dynamic_cast<Class*>(symbol.get()))
{
if (cls->members)
{
CacheScopeRecursive(cls->members.get());
}
}
// 递归缓存函数体作用域
if (auto* func = dynamic_cast<Function*>(symbol.get()))
{
if (func->body_scope)
{
CacheScopeRecursive(func->body_scope.get());
}
}
// 递归缓存构造函数体作用域
if (auto* ctor = dynamic_cast<Constructor*>(symbol.get()))
{
if (ctor->body_scope)
{
CacheScopeRecursive(ctor->body_scope.get());
}
}
// 递归缓存析构函数体作用域
if (auto* dtor = dynamic_cast<Destructor*>(symbol.get()))
{
if (dtor->body_scope)
{
CacheScopeRecursive(dtor->body_scope.get());
}
}
}
}
// ==================== 管理接口 ====================
void IncrementalEngine::Clear()
{
cache_.Clear();
}
void IncrementalEngine::SetMaxCacheSize(size_t max_size)
{
max_cache_size_ = max_size;
cache_.SetMaxSize(max_size);
}
size_t IncrementalEngine::GetCacheSize() const
{
return cache_.Size();
}
}
@@ -0,0 +1,75 @@
#pragma once
#include "../../ast/types.hpp"
#include "../core/registry.hpp"
#include "../core/table.hpp"
#include "./incremental.hpp"
namespace lsp::language::symbol
{
/**
* 增量构建引擎 - 管理符号缓存和复用
*
* 职责:
* - 管理符号缓存 (SymbolCache)
* - 提供符号复用接口
* - 提供符号缓存接口
* - 构建全局缓存
*
* 不负责:
* - 依赖追踪(移到语义分析阶段)
* - 类型解析(移到语义分析阶段)
*/
class IncrementalEngine
{
public:
IncrementalEngine();
// ==================== 符号复用与缓存 ====================
/**
* 尝试从缓存复用符号
* @param node AST 节点
* @param scope 当前作用域
* @param registry 符号注册表(用于 Unit 复用)
* @return 是否成功复用
*/
bool TryReuseSymbol(const ast::ASTNode& node, Table* scope, SymbolRegistry* registry = nullptr);
/**
* 缓存当前符号
* @param node AST 节点
* @param scope 当前作用域
*/
void CacheSymbol(const ast::ASTNode& node, Table* scope);
/**
* 从整个注册表构建缓存
* @param registry 符号注册表
*/
void BuildCache(const SymbolRegistry& registry);
// ==================== 管理接口 ====================
void Clear();
void SetMaxCacheSize(size_t max_size);
size_t GetCacheSize() const;
// 访问器
SymbolCache& GetCache() { return cache_; }
const SymbolCache& GetCache() const { return cache_; }
private:
// ==================== 内部辅助方法 ====================
// 递归缓存作用域中的所有符号
void CacheScopeRecursive(Table* scope);
// 尝试复用 Unit
bool TryReuseUnit(const ast::UnitDefinition& unit_ast, SymbolRegistry* registry);
private:
SymbolCache cache_;
size_t max_cache_size_;
};
}
@@ -0,0 +1,59 @@
#include "./type.hpp"
#include <sstream>
#include <cctype>
namespace lsp::language::symbol
{
// ==================== TypeFactory 实现 ====================
TypeInfo TypeFactory::FromAnnotation(const std::string& annotation)
{
// 直接存储原始注解字符串,不做任何解析
// 类型引用的解析将在语义分析阶段完成
return TypeInfo(Trim(annotation));
}
std::string TypeFactory::Trim(const std::string& str)
{
size_t start = 0;
while (start < str.length() && std::isspace(static_cast<unsigned char>(str[start])))
++start;
if (start == str.length())
return "";
size_t end = str.length();
while (end > start && std::isspace(static_cast<unsigned char>(str[end - 1])))
--end;
return str.substr(start, end - start);
}
// ==================== TypeFormatter 实现 ====================
std::string TypeFormatter::ToString(const TypeInfo& type)
{
if (!type.HasAnnotation())
return "<no annotation>";
return type.Annotation();
}
std::string TypeFormatter::ToDebugString(const TypeInfo& type)
{
std::ostringstream oss;
oss << "TypeInfo { ";
if (type.HasAnnotation())
{
oss << "annotation: \"" << type.Annotation() << "\"";
}
else
{
oss << "no annotation";
}
oss << " }";
return oss.str();
}
}
@@ -0,0 +1,57 @@
#pragma once
#include <string>
#include "../core/symbol.hpp"
namespace lsp::language::symbol
{
// ==================== 类型工厂 ====================
/**
* 类型工厂 - 仅用于符号表构建
*
* 职责:
* - 从类型注解字符串创建 TypeInfo
* - 存储原始字符串,不解析任何引用
*
* 不负责:
* - 类型引用解析(属于语义分析)
* - 表达式解析(属于语义分析)
* - 类型检查(属于语义分析)
*/
class TypeFactory
{
public:
/**
* 从类型注解创建 TypeInfo
* @param annotation 类型注解字符串(如 "Integer", "TMyClass"
* @return TypeInfo 对象
*
* 注意:直接存储原始字符串,不做任何解析
*/
static TypeInfo FromAnnotation(const std::string& annotation);
private:
// 辅助函数:去除首尾空格
static std::string Trim(const std::string& str);
};
// ==================== 类型格式化器 ====================
/**
* 类型格式化器 - 用于调试和日志输出
*/
class TypeFormatter
{
public:
/**
* 转换为可读字符串
*/
static std::string ToString(const TypeInfo& type);
/**
* 转换为调试字符串(包含详细信息)
*/
static std::string ToDebugString(const TypeInfo& type);
};
}