版本:v0.0.1
适用范围:编译器设计与实现的通用架构指南
关联项目:BitUI 框架编译器、未来的 Bit 语言编译器
- BitUI 编译器实现 - 基于本指南的实际实现
- Bit HCI 技术架构 - 整体技术框架
- BitUI 编译器开发文档 - BitUI 框架特定实现
- 文档中心 - 所有文档导航
- 编译器总体架构
- 词法分析器(Lexer)
- 语法分析器(Parser)
- 抽象语法树(AST)
- 语义分析器(Semantic Analyzer)
- 中间表示(IR)
- 代码生成器(Code Generator)
- 新语法扩展流程
- 最佳实践与设计模式
现代编译器采用分阶段的模块化架构,每个阶段负责特定的转换任务:
| 阶段 | 输入 | 输出 | 职责 |
|---|---|---|---|
| 词法分析 | 源代码字符串 | Token 流 | 将字符流分割为词法单元 |
| 语法分析 | Token 流 | AST | 构建语法结构树 |
| 语义分析 | AST | 带类型的 AST | 类型检查、作用域分析 |
| 中间代码生成 | AST | IR | 生成平台无关的中间表示 |
| 优化 | IR | 优化后的 IR | 代码优化(常量折叠、死代码消除等) |
| 目标代码生成 | IR | 目标代码 | 生成特定平台的机器码或字节码 |
- 关注点分离:每个阶段只关注自己的职责
- 数据驱动:阶段之间通过标准数据结构通信
- 可扩展性:易于添加新特性而不破坏现有结构
- 错误恢复:在每个阶段提供良好的错误诊断和恢复
将源代码字符流转换为有意义的 Token 序列。
enum class TokenType {
// 字面量类型
IDENTIFIER, // 标识符
STRING_LITERAL, // 字符串字面量
NUMBER_LITERAL, // 数字字面量
// 关键字(语言特定)
KEYWORD_START,
FUNCTION, CLASS, IF, ELSE, FOR, WHILE,
KEYWORD_END,
// 操作符
PLUS, MINUS, MULTIPLY, DIVIDE,
ASSIGN, EQUAL, NOT_EQUAL,
LESS, GREATER, LESS_EQUAL, GREATER_EQUAL,
// 分隔符
LEFT_PAREN, RIGHT_PAREN, // ( )
LEFT_BRACE, RIGHT_BRACE, // { }
LEFT_BRACKET, RIGHT_BRACKET, // [ ]
COMMA, SEMICOLON, COLON,
// 特殊
EOF_TOKEN,
UNKNOWN
};
struct Token {
TokenType type;
std::string value; // 原始字符串值
size_t line; // 行号
size_t column; // 列号
Token(TokenType t, const std::string& v, size_t l, size_t c)
: type(t), value(v), line(l), column(c) {}
};class Lexer {
public:
explicit Lexer(const std::string& source);
std::vector<Token> tokenize();
private:
std::string source;
size_t position;
size_t line;
size_t column;
// 核心方法
Token nextToken();
Token readIdentifierOrKeyword();
Token readNumber();
Token readString();
Token readOperator();
// 辅助方法
char peek();
char peek(size_t offset);
char advance();
bool match(char expected);
bool isAtEnd();
void skipWhitespace();
void skipComment();
};Token Lexer::readIdentifierOrKeyword() {
size_t start = position;
while (isAlphaNumeric(peek())) {
advance();
}
std::string text = source.substr(start, position - start);
// 使用哈希表或 switch 进行关键字查找
static const std::unordered_map<std::string, TokenType> keywords = {
{"function", TokenType::FUNCTION},
{"class", TokenType::CLASS},
{"if", TokenType::IF},
{"else", TokenType::ELSE},
// ... 更多关键字
};
auto it = keywords.find(text);
if (it != keywords.end()) {
return Token(it->second, text, line, column);
}
return Token(TokenType::IDENTIFIER, text, line, column);
}Token Lexer::readOperator() {
char c = peek();
switch (c) {
case '+':
advance();
if (match('=')) return Token(TokenType::PLUS_ASSIGN, "+=", line, column);
return Token(TokenType::PLUS, "+", line, column);
case '-':
advance();
if (match('>')) return Token(TokenType::ARROW, "->", line, column);
if (match('=')) return Token(TokenType::MINUS_ASSIGN, "-=", line, column);
return Token(TokenType::MINUS, "-", line, column);
case '=':
advance();
if (match('=')) return Token(TokenType::EQUAL, "==", line, column);
return Token(TokenType::ASSIGN, "=", line, column);
// ... 更多操作符
}
}常见的解析方法:
- 递归下降解析:手写,易于理解和调试(推荐用于中小型语言)
- LL(k) 解析:从左到右扫描,从左到右推导
- LR(k) 解析:从左到右扫描,从右到左推导(更强大,但更复杂)
class Parser {
public:
explicit Parser(const std::string& source);
std::unique_ptr<Program> parse();
private:
std::vector<Token> tokens;
size_t current;
// 语句解析
std::unique_ptr<Stmt> parseStatement();
std::unique_ptr<Stmt> parseDeclaration();
std::unique_ptr<Stmt> parseFunctionDef();
std::unique_ptr<Stmt> parseClassDef();
std::unique_ptr<Stmt> parseIfStmt();
std::unique_ptr<Stmt> parseWhileStmt();
std::unique_ptr<Stmt> parseForStmt();
std::unique_ptr<Stmt> parseReturnStmt();
// 表达式解析(优先级递降)
std::unique_ptr<Expr> parseExpression();
std::unique_ptr<Expr> parseAssignment();
std::unique_ptr<Expr> parseLogicalOr();
std::unique_ptr<Expr> parseLogicalAnd();
std::unique_ptr<Expr> parseEquality();
std::unique_ptr<Expr> parseComparison();
std::unique_ptr<Expr> parseAddition();
std::unique_ptr<Expr> parseMultiplication();
std::unique_ptr<Expr> parseUnary();
std::unique_ptr<Expr> parseCall();
std::unique_ptr<Expr> parsePrimary();
// 辅助方法
bool match(TokenType type);
bool check(TokenType type);
Token& advance();
Token& consume(TokenType type, const std::string& message);
bool isAtEnd();
void error(const std::string& message);
void synchronize(); // 错误恢复
};使用 Pratt 解析器或递归下降处理操作符优先级:
// 示例:二元表达式解析
std::unique_ptr<Expr> Parser::parseAddition() {
auto expr = parseMultiplication();
while (match(TokenType::PLUS) || match(TokenType::MINUS)) {
Token op = tokens[current - 1];
auto right = parseMultiplication();
expr = std::make_unique<BinaryExpr>(
std::move(expr),
op.value,
std::move(right)
);
}
return expr;
}void Parser::synchronize() {
advance();
while (!isAtEnd()) {
// 在语句边界恢复
if (tokens[current - 1].type == TokenType::SEMICOLON) return;
switch (tokens[current].type) {
case TokenType::CLASS:
case TokenType::FUNCTION:
case TokenType::IF:
case TokenType::FOR:
case TokenType::RETURN:
return;
}
advance();
}
}// 基类
class ASTNode {
public:
virtual ~ASTNode() = default;
virtual void accept(ASTVisitor& visitor) = 0;
virtual std::string toString() const = 0;
size_t line = 0;
size_t column = 0;
};
// 表达式基类
class Expr : public ASTNode {
public:
virtual ~Expr() = default;
};
// 语句基类
class Stmt : public ASTNode {
public:
virtual ~Stmt() = default;
};class ASTVisitor {
public:
virtual ~ASTVisitor() = default;
// 表达式访问
virtual void visit(BinaryExpr& expr) = 0;
virtual void visit(UnaryExpr& expr) = 0;
virtual void visit(LiteralExpr& expr) = 0;
virtual void visit(IdentifierExpr& expr) = 0;
virtual void visit(CallExpr& expr) = 0;
// 语句访问
virtual void visit(FunctionDef& stmt) = 0;
virtual void visit(ClassDef& stmt) = 0;
virtual void visit(IfStmt& stmt) = 0;
virtual void visit(WhileStmt& stmt) = 0;
virtual void visit(ReturnStmt& stmt) = 0;
// 程序根节点
virtual void visit(Program& program) = 0;
};// 二元表达式
class BinaryExpr : public Expr {
public:
std::unique_ptr<Expr> left;
std::string op;
std::unique_ptr<Expr> right;
};
// 函数定义
class FunctionDef : public Stmt {
public:
std::string name;
std::vector<Parameter> params;
std::unique_ptr<Type> returnType;
std::vector<std::unique_ptr<Stmt>> body;
};
// 条件语句
class IfStmt : public Stmt {
public:
std::unique_ptr<Expr> condition;
std::vector<std::unique_ptr<Stmt>> thenBranch;
std::vector<std::unique_ptr<Stmt>> elseBranch;
};- 作用域分析:变量声明与引用的绑定
- 类型检查:表达式类型推导与检查
- 语义验证:如 break/continue 必须在循环内
class SymbolTable {
public:
void enterScope();
void exitScope();
void define(const std::string& name, Symbol symbol);
Symbol* resolve(const std::string& name);
bool isDefined(const std::string& name) const;
private:
std::vector<std::unordered_map<std::string, Symbol>> scopes;
};
struct Symbol {
std::string name;
std::unique_ptr<Type> type;
bool isConstant;
size_t scopeLevel;
};class TypeChecker : public ASTVisitor {
public:
void visit(BinaryExpr& expr) override {
expr.left->accept(*this);
expr.right->accept(*this);
Type* leftType = getExprType(expr.left.get());
Type* rightType = getExprType(expr.right.get());
if (!areTypesCompatible(leftType, rightType, expr.op)) {
error("Type mismatch in binary expression");
}
setExprType(&expr, computeResultType(leftType, rightType, expr.op));
}
};- 三地址码(TAC):简单,易于优化
- SSA 形式:每个变量只赋值一次,便于优化
- LLVM IR:工业级 IR,功能强大
// 源代码: a = b + c * d
t1 = c * d
t2 = b + t1
a = t2
将 IR 转换为目标平台代码:
- 机器码
- 字节码
- JavaScript/C++ 等高级语言
class CodeGenerator {
public:
std::string generate(const Program& program);
private:
void generateStmt(const Stmt& stmt);
void generateExpr(const Expr& expr);
std::stringstream output;
int tempCounter = 0;
int labelCounter = 0;
};| 步骤 | 操作 | 文件 |
|---|---|---|
| 1 | 定义新 Token 类型 | lexer.h |
| 2 | 实现词法识别 | lexer.cpp |
| 3 | 定义 AST 节点 | ast.h |
| 4 | 实现语法解析 | parser.cpp |
| 5 | 扩展语义分析 | semantic.cpp |
| 6 | 扩展代码生成 | codegen.cpp |
| 7 | 添加测试用例 | tests/ |
// 1. Lexer: 添加 Token
enum class TokenType {
// ...
UNLESS,
// ...
};
// 2. Parser: 解析语句
std::unique_ptr<Stmt> Parser::parseUnlessStmt() {
advance(); // skip 'unless'
consume(LEFT_PAREN, "Expected '('");
auto condition = parseExpression();
consume(RIGHT_PAREN, "Expected ')'");
auto body = parseBlock();
// unless (x) { ... } 等价于 if (!x) { ... }
auto negated = std::make_unique<UnaryExpr>("!", std::move(condition));
return std::make_unique<IfStmt>(std::move(negated), std::move(body), {});
}- 访问者模式:AST 遍历
- 建造者模式:复杂 AST 节点构建
- 策略模式:不同优化策略切换
- 工厂模式:节点创建
class CompilerError {
public:
std::string message;
size_t line;
size_t column;
ErrorLevel level; // ERROR, WARNING, INFO
std::string format() const {
return std::format("[{}:{}] {}: {}",
line, column, levelToString(level), message);
}
};- 单元测试:每个模块独立测试
- 集成测试:完整编译管线测试
- 快照测试:AST/IR 输出对比
- 语法错误测试:验证错误诊断质量
- Compilers: Principles, Techniques, and Tools (龙书)
- Modern Compiler Implementation in C (虎书)
- Engineering a Compiler (鲸书)
- BitUI 编译器:本项目的声明式 UI 框架编译器实现
- Bit 语言:未来的系统级编程语言
作者:Bit Project 团队
项目:Bit HCI / BitUI Compiler
版本:1.0.0
最后更新:2025-10-11