17370845950

如何用c++实现一个简单的词法分析器 编译器入门【项目练手】
C++词法分析器通过逐字符扫描将源码切分为token,支持关键字、标识符、整数、运算符等类型;核心类Lexer含nextToken()方法,按空格跳过、字母/下划线启标识符、数字启整数、单字符匹配运算符等规则生成Token结构。

用 C++ 实现一个简单的词法分析器,核心是把源代码字符串按规则切分成有意义的“记号”(token),比如关键字、标识符、数字、运算符等。不需要完整支持 C/C++ 语法,从识别 int a = 42; 这类基础语句开始最实用。

明确要识别的 token 类型

先定义有限但覆盖常见的 token 种类,例如:

  • 关键字:如 intreturn
  • 标识符:以字母或下划线开头,后跟字母/数字/下划线(如 abc123_x
  • 整数常量:纯数字序列(如 1230),暂不支持负数或十六进制
  • 运算符和分隔符:如 =+;()
  • 空白与换行:跳过,不生成 token

设计 Token 结构和词法器类骨架

每个 token 至少记录类型(枚举)、原始文本(string)、行号(可选)。词法器类通常包含输入字符串、当前位置索引、当前行号:

enum class TokenType {
    IDENTIFIER, INTEGER, INT_KW, RETURN_KW, ASSIGN, PLUS, SEMICOLON,
    LPAREN, RPAREN, EOF_TOKEN
};

struct Token {
    TokenType type;
    std::string lexeme;
    int line;
};

class Lexer {
    std::string input;
    size_t pos = 0;
    int line = 1;
public:
    Lexer(const std::string& src) : input(src) {}
    Token nextToken();
private:
    char peek() const { return (pos < input.size()) ? input[pos] : '\0'; }
    char advance() { return input[pos++]; }
    bool isAtEnd() const { return pos >= input.size(); }
    void skipWhitespace();
    Token scanIdentifierOrKeyword();
    Token scanNumber();
    Token scanOperator();
};

逐字符扫描 + 状态驱动识别

主函数 nextToken() 每次调用返回下一个 token,逻辑清晰:

  • 先跳过空格、制表符、换行(更新 line
  • 根据当前字符决定分支:
      – 若是字母或下划线 → 调用 scanIdentifierOrKeyword(),查表判断是否为关键字
      – 若是数字 → 调用 scanNumber(),连续读取直到非数字
      – 若是 =+; 等 → 直接返回对应 token(可扩展支持 == 等双字符运算符)
      – 若是 () → 返回对应 token
      – 否则报错或返回未知 token
  • 到达末尾时返回 EOF_TOKEN

测试与迭代建议

写个简单测试入口,输入字符串,循环调用 nextToken() 并打印结果:

int main() {
    std::string src = "int a = 42; return a;";
    Lexer lexer(src);
    Token tok;
    do {
        tok = lexer.nextToken();
        std::cout << tokenTypeToString(tok.type) << " '" << tok.lexeme << "'\n";
    } while (tok.type != TokenType::EOF_TOKEN);
}

先让 int a = 42; 正确输出 INT_KWIDENTIFIERASSIGNINTEGERSEMICOLON;再逐步加 return、括号、多行支持。遇到错误时打印位置(posline)便于调试。