版本:v0.0.1
所属项目:Bit HCI / BitUI Compiler
定位:BitUI 框架编译器的详细实现指南
- BitUI 编译器 README - 编译器使用指南和快速开始
- 通用编译器架构参考 - 理论基础与最佳实践
- Bit HCI 技术架构 - 整体架构设计
- 编译器总体架构 / Compiler Architecture Overview
- 词法分析器(Lexer) / Lexical Analyzer
- 语法分析器(Parser) / Syntax Parser
- 抽象语法树(AST) / Abstract Syntax Tree
- 新语法扩展流程 / New Syntax Extension Workflow
- 附录 / Appendix
BitUI 框架编译器采用模块化架构,主要包含五个部分:
| 模块 | 职责 |
|---|---|
| Lexer | 将源代码转换为 token 流 |
| Parser | 将 token 序列解析为语法树 |
| AST | 构建抽象语法树模型 |
| Semantic Analyzer | 检查作用域与类型一致性 |
| Code Generator | 生成目标代码(LLVM IR、Vulkan IR 等) |
The BitUI compiler follows a modular design, where each subsystem handles a specific stage of compilation, enabling easy extension and debugging.
负责将源代码字符流分割为可识别的 token 序列。
enum class TokenType {
// 字面量
IDENTIFIER, STRING_LITERAL, NUMBER_LITERAL, SIGNAL_REF, // $identifier
// 关键字
COMPONENT, SIGNAL, STATE, PROPS, CHILDREN, STYLE, EVENT,
IF, ELSE, FOR, IN,
// 操作符
ASSIGN, EQUAL, NOT_EQUAL, LESS, GREATER, LESS_EQUAL, GREATER_EQUAL,
PLUS, MINUS, MULTIPLY, DIVIDE, MODULO, AND, OR, NOT,
// 分隔符
LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, RIGHT_BRACE,
LEFT_BRACKET, RIGHT_BRACKET, COMMA, SEMICOLON, COLON, DOT, ARROW,
// 特殊
NEWLINE, EOF_TOKEN, UNKNOWN
};Token Lexer::readIdentifier() {
// 识别关键字
if (identifier == "component") return Token(TokenType::COMPONENT, identifier, line, startColumn);
if (identifier == "signal") return Token(TokenType::SIGNAL, identifier, line, startColumn);
if (identifier == "if") return Token(TokenType::IF, identifier, line, startColumn);
if (identifier == "for") return Token(TokenType::FOR, identifier, line, startColumn);
// 普通标识符
return Token(TokenType::IDENTIFIER, identifier, line, startColumn);
}// 处理 -> 箭头操作符
if (c == '-') {
advance();
if (match('>')) {
return Token(TokenType::ARROW, "->", line, column - 1);
}
return Token(TokenType::MINUS, "-", line, column - 1);
}
// 信号引用 $identifier
if (c == '$') {
advance(); // 跳过 '$'
if (isAlpha(peek()) || peek() == '_') {
return readSignalRef();
}
}将 token 流转换为语法树(AST)。
Each parsing function corresponds to a syntactic construct (e.g., function definition, class declaration, variable declaration).
std::unique_ptr<Stmt> parseComponentDef();
std::unique_ptr<Stmt> parseSignalDef();
std::unique_ptr<Stmt> parseIfStmt();
std::unique_ptr<Stmt> parseForStmt();
std::unique_ptr<Expr> parseExpression();std::unique_ptr<Stmt> Parser::parseComponentDef() {
advance(); // skip 'component'
if (!check(TokenType::IDENTIFIER)) {
error("Expected component name");
return nullptr;
}
std::string name = currentToken().value;
advance(); // 跳过组件名
if (!match(TokenType::LEFT_BRACE)) {
error("Expected '{' after component name");
return nullptr;
}
auto props = parseComponentProps();
auto children = parseComponentChildren();
if (!match(TokenType::RIGHT_BRACE)) {
error("Expected '}' after component body");
return nullptr;
}
return std::make_unique<ComponentDef>(name, std::move(props), std::move(children));
}std::unique_ptr<Stmt> Parser::parseSignalDef() {
advance(); // skip 'signal'
if (!check(TokenType::IDENTIFIER)) {
error("Expected signal name");
return nullptr;
}
std::string name = currentToken().value;
advance(); // 跳过信号名
if (!match(TokenType::ASSIGN)) {
error("Expected '=' after signal name");
return nullptr;
}
auto initialValue = parseExpression();
if (!initialValue) {
error("Expected initial value for signal");
return nullptr;
}
return std::make_unique<SignalDef>(name, std::move(initialValue));
}std::unique_ptr<Stmt> Parser::parseStatement() {
if (check(TokenType::COMPONENT)) return parseComponentDef();
if (check(TokenType::SIGNAL)) return parseSignalDef();
if (check(TokenType::IF)) return parseIfStmt();
if (check(TokenType::FOR)) return parseForStmt();
// 尝试解析表达式语句
auto expr = parseExpression();
if (expr) {
return std::make_unique<ExpressionStmt>(std::move(expr));
}
error("Unexpected token: " + currentToken().value);
return nullptr;
}定义语言结构的统一抽象表达。
Each AST node represents a high-level construct and supports the Visitor pattern.
// 组件定义
class ComponentDef : public Stmt {
public:
std::string name;
std::vector<ComponentProp> props;
std::vector<std::unique_ptr<Stmt>> children;
};
// 信号定义
class SignalDef : public Stmt {
public:
std::string name;
std::unique_ptr<Expr> initialValue;
};
// 条件语句
class IfStmt : public Stmt {
public:
std::unique_ptr<Expr> condition;
std::vector<std::unique_ptr<Stmt>> thenBranch;
std::vector<std::unique_ptr<Stmt>> elseBranch;
};
// 循环语句
class ForStmt : public Stmt {
public:
std::string variable;
std::unique_ptr<Expr> iterable;
std::vector<std::unique_ptr<Stmt>> body;
};class ASTVisitor {
public:
virtual ~ASTVisitor() = default;
// 表达式节点
virtual void visit(LiteralExpr& expr) = 0;
virtual void visit(IdentifierExpr& expr) = 0;
virtual void visit(BinaryExpr& expr) = 0;
virtual void visit(CallExpr& expr) = 0;
virtual void visit(SignalExpr& expr) = 0;
// 语句节点
virtual void visit(ComponentDef& stmt) = 0;
virtual void visit(SignalDef& stmt) = 0;
virtual void visit(IfStmt& stmt) = 0;
virtual void visit(ForStmt& stmt) = 0;
virtual void visit(Program& program) = 0;
};| 步骤 / Step | 说明 / Description |
|---|---|
1️⃣ 修改 TokenType |
添加新关键字或操作符 |
2️⃣ 扩展 lexer.cpp |
实现关键字识别与符号解析 |
3️⃣ 更新 parser.h/.cpp |
增加对应语法解析函数 |
4️⃣ 扩展 AST |
定义新语法节点 |
| 5️⃣ 注册解析入口 | 在 parseStatement() 中添加分支 |
| 6️⃣ (可选)语义与生成 | 在语义分析和 IR 生成阶段扩展支持 |
模块化设计使得添加新语法无需重写核心编译流程,只需扩展对应模块。
void Parser::error(const std::string& message) {
std::cerr << "[Line " << line << "] Error: " << message << std::endl;
}- 所有 Token 使用全大写命名。
- 所有 AST 节点以 PascalCase 命名。
- 所有解析函数以
parseXxx()命名。
- 泛型与模板系统 (Generics / Templates)
- 类型推断系统 (Type Inference)
- LLVM/Vulkan 双后端编译支持
作者 / Author: 陈智鹏 (Chen Zhipeng)
项目 / Project: BitUI Compiler Core
版本 / Version: 1.0.0