Skip to content

Latest commit

 

History

History
583 lines (449 loc) · 14 KB

File metadata and controls

583 lines (449 loc) · 14 KB

🧠 通用编译器架构参考指南

版本:v0.0.1
适用范围:编译器设计与实现的通用架构指南
关联项目:BitUI 框架编译器、未来的 Bit 语言编译器

📚 相关文档


📋 目录

  1. 编译器总体架构
  2. 词法分析器(Lexer)
  3. 语法分析器(Parser)
  4. 抽象语法树(AST)
  5. 语义分析器(Semantic Analyzer)
  6. 中间表示(IR)
  7. 代码生成器(Code Generator)
  8. 新语法扩展流程
  9. 最佳实践与设计模式

1. 编译器总体架构

1.1 模块化设计

现代编译器采用分阶段的模块化架构,每个阶段负责特定的转换任务:

阶段 输入 输出 职责
词法分析 源代码字符串 Token 流 将字符流分割为词法单元
语法分析 Token 流 AST 构建语法结构树
语义分析 AST 带类型的 AST 类型检查、作用域分析
中间代码生成 AST IR 生成平台无关的中间表示
优化 IR 优化后的 IR 代码优化(常量折叠、死代码消除等)
目标代码生成 IR 目标代码 生成特定平台的机器码或字节码

1.2 设计原则

  • 关注点分离:每个阶段只关注自己的职责
  • 数据驱动:阶段之间通过标准数据结构通信
  • 可扩展性:易于添加新特性而不破坏现有结构
  • 错误恢复:在每个阶段提供良好的错误诊断和恢复

2. 词法分析器(Lexer)

2.1 核心职责

将源代码字符流转换为有意义的 Token 序列。

2.2 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) {}
};

2.3 核心算法

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();
};

2.4 关键字识别模式

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);
}

2.5 操作符处理

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);
            
        // ... 更多操作符
    }
}

3. 语法分析器(Parser)

3.1 解析策略

常见的解析方法:

  • 递归下降解析:手写,易于理解和调试(推荐用于中小型语言)
  • LL(k) 解析:从左到右扫描,从左到右推导
  • LR(k) 解析:从左到右扫描,从右到左推导(更强大,但更复杂)

3.2 递归下降解析器结构

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();  // 错误恢复
};

3.3 表达式优先级解析

使用 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;
}

3.4 错误处理与恢复

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();
    }
}

4. 抽象语法树(AST)

4.1 节点设计

// 基类
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;
};

4.2 访问者模式

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;
};

4.3 常用节点类型

// 二元表达式
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;
};

5. 语义分析器(Semantic Analyzer)

5.1 核心任务

  • 作用域分析:变量声明与引用的绑定
  • 类型检查:表达式类型推导与检查
  • 语义验证:如 break/continue 必须在循环内

5.2 符号表设计

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;
};

5.3 类型检查示例

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));
    }
};

6. 中间表示(IR)

6.1 常见 IR 类型

  • 三地址码(TAC):简单,易于优化
  • SSA 形式:每个变量只赋值一次,便于优化
  • LLVM IR:工业级 IR,功能强大

6.2 三地址码示例

// 源代码: a = b + c * d
t1 = c * d
t2 = b + t1
a = t2

7. 代码生成器(Code Generator)

7.1 目标

将 IR 转换为目标平台代码:

  • 机器码
  • 字节码
  • JavaScript/C++ 等高级语言

7.2 基本策略

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;
};

8. 新语法扩展流程

8.1 标准流程

步骤 操作 文件
1 定义新 Token 类型 lexer.h
2 实现词法识别 lexer.cpp
3 定义 AST 节点 ast.h
4 实现语法解析 parser.cpp
5 扩展语义分析 semantic.cpp
6 扩展代码生成 codegen.cpp
7 添加测试用例 tests/

8.2 示例:添加 unless 关键字

// 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), {});
}

9. 最佳实践与设计模式

9.1 设计模式

  • 访问者模式:AST 遍历
  • 建造者模式:复杂 AST 节点构建
  • 策略模式:不同优化策略切换
  • 工厂模式:节点创建

9.2 错误处理

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);
    }
};

9.3 测试策略

  • 单元测试:每个模块独立测试
  • 集成测试:完整编译管线测试
  • 快照测试:AST/IR 输出对比
  • 语法错误测试:验证错误诊断质量

10. 参考资源

10.1 经典教材

  • Compilers: Principles, Techniques, and Tools (龙书)
  • Modern Compiler Implementation in C (虎书)
  • Engineering a Compiler (鲸书)

10.2 在线资源

10.3 实践项目

  • BitUI 编译器:本项目的声明式 UI 框架编译器实现
  • Bit 语言:未来的系统级编程语言

作者:Bit Project 团队
项目:Bit HCI / BitUI Compiler
版本:1.0.0
最后更新:2025-10-11