← 返回目录

第二章:词法分析 Lexer

实现 MiniLang Lexer,把字符流切分为 TokenType、字面量和源码位置。

1. Token 与源码位置

Lexer 负责把字符流拆成 Token,并给每个 Token 标注源码位置。关键字不是普通标识符,注释跳过、字符串扫描和 Position 记录会直接影响后续诊断质量。这里的 关键字 表会把 let、fn、if、while 映射为专门的 TokenType。

enum TokenType {
  Identifier,
  Number,
  String,
  Let,
  Fn,
  If,
  While,
  Equal,
  EOF,
}

type Position = { line: number; column: number; offset: number };
const keywords = new Map<string, TokenType>([
  ["let", TokenType.Let],
  ["fn", TokenType.Fn],
  ["if", TokenType.If],
  ["while", TokenType.While],
]);

2. 扫描 MiniLang

扫描器要处理空白、comment skipping、字符串扫描和源码位置推进。MiniLang 示例 let name: string = "compiler"; 会被拆成 let 关键字、name 标识符、string 类型名、等号和字符串字面量。

class Lexer {
  constructor(private source: string, private current = 0) {}

  scanTokens(): Token[] {
    const tokens: Token[] = [];
    while (!this.isAtEnd()) tokens.push(this.scanToken());
    tokens.push({ type: TokenType.EOF, lexeme: "", position: this.position() });
    return tokens;
  }

  private scanString(): Token {
    // let name: string = "compiler";
    return { type: TokenType.String, lexeme: this.readUntilQuote(), position: this.position() };
  }
}
上一章:语言与编译器全景 返回目录 下一章:语法分析 Parser