Lexer & Parser

编译原理中,LexerParser 结合在一起可以将代码转为 AST 抽象语法树,以进行后序AST转译代码生成等步骤。本文章主要解析一下LexerParser 的具体定义。



Lexer

终结符 & 生产式 & 文法中,可以知道程序的最小组成单位是终结符,而Lexer就是将代码分割成终结符的程序 lexer

if (var1 > 0) {
  let var1 = 1; 
}

可以使用espree这个Javascript解析库来尝试获取下lexer的结果,

import * as espree from 'espree';

const code = `
if (var1 > 0) {
  let var1 = 1; 
}
`;

const options = {
    ecmaVersion: 2022,    // 使用最新的 ECMAScript 版本
    sourceType: 'module', // 支持 ES 模块语法
    comment: true,        // 包含注释
    tokens: true,         // 生成词法标记
    range: true,         // 添加范围属性
    loc: true           // 添加行列位置信息
};

const tokens = espree.tokenize(code, options);
console.log(tokens);

运行后输出的Tokens包括Token的类型,内容还有在源码的位置信息,并且会发现输出的Tokens中,无意义字符(例如空格,换行符) 等被去掉,代表Lexer还有数据清洗的作用。

Token {
    type: 'Keyword',
    value: 'if',
    start: 1,
    end: 3,
    loc: SourceLocation { start: [Position], end: [Position] },
    range: [ 1, 3 ]
},
...

Parser

Parser是将Lexer的到Tokens,转为下面具有语法意义的AST抽象语法树的程序 ast 同样可以使用espree体验输出的AST,或者可以使用astexplorer更直观地查看。

import * as espree from 'espree';

const code = `
if (var1 > 0) {
  let var1 = 1; 
}
`;

const options = {
    ecmaVersion: 2022,    // 使用最新的 ECMAScript 版本
    sourceType: 'module', // 支持 ES 模块语法
    comment: true,        // 包含注释
    tokens: true,         // 生成词法标记
    range: true,         // 添加范围属性
    loc: true           // 添加行列位置信息
};
const ast = espree.parse(code, options);
console.log(ast);