update test file
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
cmake_minimum_required(VERSION 4.0)
|
||||
|
||||
project(test_ast)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
message(STATUS "CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}")
|
||||
message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
|
||||
message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
if (DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
message(STATUS ">>> CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}")
|
||||
endif()
|
||||
if (DEFINED VCPKG_TARGET_TRIPLET)
|
||||
message(STATUS ">>> VCPKG_TARGET_TRIPLET: ${VCPKG_TARGET_TRIPLET}")
|
||||
endif()
|
||||
|
||||
# 设置默认构建类型
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE
|
||||
"Release"
|
||||
CACHE STRING "Build type" FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
|
||||
"MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
# MinGW/MSYS2 静态链接
|
||||
if(MINGW)
|
||||
add_link_options(-static -static-libgcc -static-libstdc++)
|
||||
elseif(UNIX AND NOT APPLE) # Linux 静态链接
|
||||
add_link_options(-static-libgcc -static-libstdc++)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".lib" ".dll.a")
|
||||
else()
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".so")
|
||||
endif()
|
||||
|
||||
find_package(glaze CONFIG REQUIRED)
|
||||
find_package(spdlog CONFIG REQUIRED)
|
||||
find_package(fmt CONFIG REQUIRED)
|
||||
find_package(Taskflow REQUIRED)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
if(DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
find_package(unofficial-tree-sitter CONFIG REQUIRED)
|
||||
set(TREESITTER_TARGET unofficial::tree-sitter::tree-sitter)
|
||||
else()
|
||||
# find_package(PkgConfig REQUIRED)
|
||||
# pkg_check_modules(TREESITTER tree-sitter)
|
||||
find_library(TREESITTER_LIBRARY tree-sitter) # use ${TREESITTER_LIBRARY}
|
||||
set(TREESITTER_TARGET ${TREESITTER_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(NOT TARGET spdlog::spdlog_header_only)
|
||||
message(WARNING "spdlog header-only target not found, using shared library")
|
||||
endif()
|
||||
if(NOT TARGET fmt::fmt-header-only)
|
||||
message(WARNING "fmt header-only target not found, using shared library")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
set(SOURCES
|
||||
./test.cpp
|
||||
./debug_printer.cpp
|
||||
../../src/language/ast/deserializer.cpp
|
||||
../../src/language/ast/detail.cpp
|
||||
../../src/language/ast/tree_sitter_utils.cpp
|
||||
../../src/utils/string.cpp
|
||||
../../src/tree-sitter/parser.c)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE src)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE SPDLOG_HEADER_ONLY
|
||||
FMT_HEADER_ONLY)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
glaze::glaze
|
||||
Taskflow::Taskflow
|
||||
spdlog::spdlog_header_only
|
||||
fmt::fmt-header-only
|
||||
${TREESITTER_TARGET} # 使用变量,避免条件判断
|
||||
$<$<PLATFORM_ID:Linux>:Threads::Threads> # 使用生成器表达式
|
||||
)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE
|
||||
-Wall -Wextra -Wpedantic
|
||||
$<$<CONFIG:Debug>:-g -O0>
|
||||
$<$<CONFIG:Release>:-O3>
|
||||
)
|
||||
endif()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "../../src/language/ast/types.hpp"
|
||||
#include "../../src/language/ast/deserializer.hpp"
|
||||
|
||||
namespace lsp::language::ast
|
||||
{
|
||||
class DebugPrinter : public ASTVisitor
|
||||
{
|
||||
public:
|
||||
explicit DebugPrinter(std::ostream& os = std::cout, int indent_size = 2) :
|
||||
os_(os), indent_size_(indent_size), current_indent_(0) {}
|
||||
|
||||
void Print(const ASTNode* node);
|
||||
void PrintStatements(const std::vector<StatementPtr>& statements);
|
||||
void PrintParseResult(const ParseResult& result);
|
||||
|
||||
void VisitUnitDefinition(UnitDefinition& node) override;
|
||||
void VisitClassDefinition(ClassDefinition& node) override;
|
||||
void VisitClassMember(ClassMember& node) override;
|
||||
void VisitMethodDeclaration(MethodDeclaration& node) override;
|
||||
void VisitPropertyDeclaration(PropertyDeclaration& node) override;
|
||||
void VisitExternalMethodDefinition(ExternalMethodDefinition& node) override;
|
||||
void VisitIdentifier(Identifier& node) override;
|
||||
void VisitLiteral(Literal& node) override;
|
||||
void VisitBinaryExpression(BinaryExpression& node) override;
|
||||
void VisitComparisonExpression(ComparisonExpression& node) override;
|
||||
void VisitUnaryExpression(UnaryExpression& node) override;
|
||||
void VisitTernaryExpression(TernaryExpression& node) override;
|
||||
void VisitCallExpression(CallExpression& node) override;
|
||||
void VisitAttributeExpression(AttributeExpression& node) override;
|
||||
void VisitSubscriptExpression(SubscriptExpression& node) override;
|
||||
void VisitArrayExpression(ArrayExpression& node) override;
|
||||
void VisitAnonymousFunctionExpression(AnonymousFunctionExpression& node) override;
|
||||
void VisitPrefixIncrementExpression(PrefixIncrementExpression& node) override;
|
||||
void VisitPrefixDecrementExpression(PrefixDecrementExpression& node) override;
|
||||
void VisitPostfixIncrementExpression(PostfixIncrementExpression& node) override;
|
||||
void VisitPostfixDecrementExpression(PostfixDecrementExpression& node) override;
|
||||
void VisitFunctionPointerExpression(FunctionPointerExpression& node) override;
|
||||
void VisitAssignmentExpression(AssignmentExpression& node) override;
|
||||
void VisitExpressionStatement(ExpressionStatement& node) override;
|
||||
void VisitVarStatement(VarStatement& node) override;
|
||||
void VisitStaticStatement(StaticStatement& node) override;
|
||||
void VisitGlobalStatement(GlobalStatement& node) override;
|
||||
void VisitConstStatement(ConstStatement& node) override;
|
||||
void VisitAssignmentStatement(AssignmentStatement& node) override;
|
||||
void VisitBlockStatement(BlockStatement& node) override;
|
||||
void VisitIfStatement(IfStatement& node) override;
|
||||
void VisitForInStatement(ForInStatement& node) override;
|
||||
void VisitForToStatement(ForToStatement& node) override;
|
||||
void VisitWhileStatement(WhileStatement& node) override;
|
||||
void VisitRepeatStatement(RepeatStatement& node) override;
|
||||
void VisitCaseStatement(CaseStatement& node) override;
|
||||
void VisitTryStatement(TryStatement& node) override;
|
||||
void VisitBreakStatement(BreakStatement& node) override;
|
||||
void VisitContinueStatement(ContinueStatement& node) override;
|
||||
void VisitReturnStatement(ReturnStatement& node) override;
|
||||
void VisitUsesStatement(UsesStatement& node) override;
|
||||
void VisitFunctionDefinition(FunctionDefinition& node) override;
|
||||
void VisitFunctionDeclaration(FunctionDeclaration& node) override;
|
||||
void VisitVarDeclaration(VarDeclaration& node) override;
|
||||
void VisitStaticDeclaration(StaticDeclaration& node) override;
|
||||
void VisitGlobalDeclaration(GlobalDeclaration& node) override;
|
||||
void VisitFieldDeclaration(FieldDeclaration& node) override;
|
||||
void VisitUnpackPattern(UnpackPattern& node) override;
|
||||
void VisitTSSQLExpression(TSSQLExpression& node) override;
|
||||
|
||||
private:
|
||||
std::ostream& os_;
|
||||
int indent_size_;
|
||||
int current_indent_;
|
||||
|
||||
void IncreaseIndent() { current_indent_ += indent_size_; }
|
||||
void DecreaseIndent() { current_indent_ -= indent_size_; }
|
||||
void PrintIndent();
|
||||
std::string GetIndent() const;
|
||||
|
||||
void PrintLocation(const Location& loc);
|
||||
void PrintNodeHeader(const std::string& type_name, const Location& loc);
|
||||
void PrintExpression(const Expression* expr);
|
||||
void PrintSignature(const Signature& sig);
|
||||
void PrintParameter(const Parameter& param);
|
||||
void PrintLeftHandSide(const LeftHandSide& lhs);
|
||||
void PrintOperator(BinaryOperator op);
|
||||
void PrintOperator(UnaryOperator op);
|
||||
void PrintOperator(AssignmentOperator op);
|
||||
void PrintLiteralKind(LiteralKind kind);
|
||||
void PrintAccessModifier(AccessModifier modifier);
|
||||
void PrintMethodModifier(MethodModifier modifier);
|
||||
void PrintReferenceModifier(ReferenceModifier modifier);
|
||||
void PrintError(const ParseError& error);
|
||||
};
|
||||
|
||||
std::string DebugString(const ASTNode* node);
|
||||
std::string DebugString(const ParseResult& result);
|
||||
void DebugPrint(const ASTNode* node);
|
||||
void DebugPrint(const ParseResult& result);
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
#include <tree_sitter/api.h>
|
||||
}
|
||||
|
||||
extern "C" const TSLanguage* tree_sitter_tsf(void);
|
||||
|
||||
#include "../../src/language/ast/deserializer.hpp"
|
||||
#include "./debug_printer.hpp"
|
||||
|
||||
using namespace lsp::language::ast;
|
||||
|
||||
// ==================== 文件读取 ====================
|
||||
|
||||
std::string ReadFile(const std::string& filepath)
|
||||
{
|
||||
std::ifstream file(filepath);
|
||||
if (!file.is_open())
|
||||
{
|
||||
throw std::runtime_error("Cannot open file: " + filepath);
|
||||
}
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << file.rdbuf();
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
// ==================== Tree-Sitter 解析 ====================
|
||||
|
||||
class TreeSitterParser
|
||||
{
|
||||
public:
|
||||
TreeSitterParser()
|
||||
{
|
||||
parser_ = ts_parser_new();
|
||||
if (!parser_)
|
||||
{
|
||||
throw std::runtime_error("Failed to create parser");
|
||||
}
|
||||
|
||||
// 设置语言
|
||||
if (!ts_parser_set_language(parser_, tree_sitter_tsf()))
|
||||
{
|
||||
ts_parser_delete(parser_);
|
||||
throw std::runtime_error("Failed to set language");
|
||||
}
|
||||
}
|
||||
|
||||
~TreeSitterParser()
|
||||
{
|
||||
if (tree_)
|
||||
{
|
||||
ts_tree_delete(tree_);
|
||||
}
|
||||
if (parser_)
|
||||
{
|
||||
ts_parser_delete(parser_);
|
||||
}
|
||||
}
|
||||
|
||||
TSTree* Parse(const std::string& source)
|
||||
{
|
||||
if (tree_)
|
||||
{
|
||||
ts_tree_delete(tree_);
|
||||
tree_ = nullptr;
|
||||
}
|
||||
|
||||
tree_ = ts_parser_parse_string(
|
||||
parser_,
|
||||
nullptr,
|
||||
source.c_str(),
|
||||
source.length());
|
||||
|
||||
if (!tree_)
|
||||
{
|
||||
throw std::runtime_error("Failed to parse source");
|
||||
}
|
||||
|
||||
return tree_;
|
||||
}
|
||||
|
||||
TSNode GetRootNode()
|
||||
{
|
||||
if (!tree_)
|
||||
{
|
||||
throw std::runtime_error("No tree available");
|
||||
}
|
||||
return ts_tree_root_node(tree_);
|
||||
}
|
||||
|
||||
private:
|
||||
TSParser* parser_ = nullptr;
|
||||
TSTree* tree_ = nullptr;
|
||||
};
|
||||
|
||||
// ==================== 主程序 ====================
|
||||
|
||||
void PrintUsage(const char* program_name)
|
||||
{
|
||||
std::cout << "Usage: " << program_name << " <file_path> [options]\n";
|
||||
std::cout << "\nOptions:\n";
|
||||
std::cout << " -v, --verbose Print verbose output\n";
|
||||
std::cout << " -i, --incremental Test incremental parsing\n";
|
||||
std::cout << " -h, --help Show this help message\n";
|
||||
std::cout << "\nExample:\n";
|
||||
std::cout << " " << program_name << " test.tsf\n";
|
||||
std::cout << " " << program_name << " test.tsf -v -s\n";
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
PrintUsage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string filepath;
|
||||
bool verbose = false;
|
||||
bool test_incremental = false;
|
||||
|
||||
// 解析命令行参数
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string arg = argv[i];
|
||||
if (arg == "-h" || arg == "--help")
|
||||
{
|
||||
PrintUsage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
else if (arg == "-v" || arg == "--verbose")
|
||||
{
|
||||
verbose = true;
|
||||
}
|
||||
else if (arg == "-i" || arg == "--incremental")
|
||||
{
|
||||
test_incremental = true;
|
||||
}
|
||||
else if (filepath.empty())
|
||||
{
|
||||
filepath = arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Unknown argument: " << arg << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 读取文件
|
||||
std::cout << "Reading file: " << filepath << "\n";
|
||||
std::string source = ReadFile(filepath);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
std::cout << "File size: " << source.length() << " bytes\n";
|
||||
std::cout << "----------------------------------------\n";
|
||||
std::cout << source << "\n";
|
||||
std::cout << "----------------------------------------\n\n";
|
||||
}
|
||||
|
||||
// 创建 Tree-Sitter 解析器
|
||||
std::cout << "Parsing with Tree-Sitter...\n";
|
||||
TreeSitterParser ts_parser;
|
||||
TSTree* tree = ts_parser.Parse(source);
|
||||
TSNode root = ts_parser.GetRootNode();
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
std::cout << "Root node type: " << ts_node_type(root) << "\n";
|
||||
std::cout << "Root node child count: " << ts_node_child_count(root) << "\n\n";
|
||||
}
|
||||
|
||||
// 创建 AST 反序列化器
|
||||
Deserializer deserializer;
|
||||
|
||||
ParseResult result;
|
||||
|
||||
if (test_incremental)
|
||||
{
|
||||
std::cout << "Using incremental parsing...\n";
|
||||
auto inc_result = deserializer.ParseIncremental(root, source);
|
||||
result = std::move(inc_result.result);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Using full parsing...\n";
|
||||
result = deserializer.Parse(root, source);
|
||||
}
|
||||
|
||||
// 打印解析结果
|
||||
std::cout << "\n";
|
||||
DebugPrint(result);
|
||||
|
||||
// 打印摘要
|
||||
std::cout << "\n========================================\n";
|
||||
std::cout << "Summary:\n";
|
||||
std::cout << " File: " << filepath << "\n";
|
||||
std::cout << " Size: " << source.length() << " bytes\n";
|
||||
std::cout << " AST Nodes: " << result.statements.size() << "\n";
|
||||
std::cout << " Errors: " << result.errors.size() << "\n";
|
||||
|
||||
if (result.HasErrors())
|
||||
{
|
||||
std::cout << " Status: FAILED (with errors)\n";
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " Status: SUCCESS\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Error: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
var d, e: boolean;
|
||||
global c, d;
|
||||
static e, f;
|
||||
const a: boolean = false;
|
||||
|
||||
var a, b: boolean := true;
|
||||
static d := "abc";
|
||||
global c := 123456;
|
||||
// e := f1();
|
||||
|
||||
// function f1(a: string; b: boolean = true): integer;
|
||||
// begin
|
||||
// end;
|
||||
|
||||
// function f2(a, b, c);overload;
|
||||
// begin
|
||||
// end;
|
||||
|
||||
// var d := 1;
|
||||
// c := false;
|
||||
// f := fa();
|
||||
Reference in New Issue
Block a user