npm 包 pegjs-import-loader 使用教程

摘要

pegjs-import-loader 是一个方便的 npm 包,可用于在编译过程中向 PEG.js 语法解析器中导入其他的语法规则,从而提高代码的可维护性和可扩展性。

本文将介绍如何使用 pegjs-import-loader,深入原理,以及使用示例。

使用方法

安装

使用 npm 安装 pegjs-import-loader。

npm install --save-dev pegjs-import-loader

配置

在 webpack 的配置文件中添加如下配置:

module: {
  rules: [
    {
      test: /\.pegjs$/,
      use: [
        {
          loader: 'pegjs-import-loader',
          options: {
            import: true,
            grammarPath: 'src/grammars',
            namespace: 'myGrammar',
          },
        },
      ],
    },
  ],
},

参数解释:

  • import:是否导入其他的语法规则,默认为 true。如果设定为 false,则只有当前文件中的规则会被编译。
  • grammarPath:存放其他语法规则的目录。默认为 '.'
  • namespace:规定编译后的 PEG.js 语法解析器所在的命名空间。默认为 'parser'

编写代码

在 PEG.js 的语法规则文件中使用 @import 指令来导入其他的语法规则。

例如,我们有如下两个语法规则文件:

src/grammars/arithmetic.pegjs

start
  = _ additive
  { return $2; }

additive
  = left:multiplicative _ "+" _ right:additive
  { return left + right; }
  / multiplicative

multiplicative
  = left:atomic _ "*" _ right:multiplicative
  { return left * right; }
  / atomic

atomic
  = "(" _ expr:additive _ ")" _ { return expr; }
  / n:number _ { return n; }

number = digits:[0-9]+ {
  return parseInt(digits.join(""));
}

_ "optional whitespace"
  = [ \t\n\r]*

@import "math";

src/grammars/math.pegjs

@namespace myGrammar

power
  = left:atomic _ "**" _ right:power
  { return Math.pow(left, right); }
  / atomic

arithmetic.pegjs 中使用 @import 指令导入了 math.pegjs 文件,并指定了 myGrammar 命名空间。这样,在编译 arithmetic.pegjs 文件时,math.pegjs 文件中的语法规则也会被编译进去,且都位于 myGrammar 命名空间内。

调用

编写好 PEG.js 语法规则文件后,可以使用命令行或其他工具来将其编译为 JavaScript 语法解析器文件。

例如,在 package.json 文件的 scripts 里添加如下命令:

{
  "scripts": {
    "build-parser": "pegjs src/grammars/arithmetic.pegjs dist/parser.js"
  }
}

然后,在命令行里运行如下命令:

npm run build-parser

即可生成 JavaScript 语法解析器文件。

原理深入

PEG.js 语法解析器是一种基于 Parsing Expression Grammar(解析表达式语法)的解析器。在编译过程中,PEG.js 将语法规则文件编译为 JavaScript 函数,并将其封装在一个对象中。

pegjs-import-loader 利用了 PEG.js 的编译时机制,可以在编译过程中向 PEG.js 语法解析器中动态地添加新的语法规则。具体来说,pegjs-import-loader 在 PEG.js 的解析器构造函数中注入了额外的解析规则。

示例

以计算器为例,我们可以编写以下 PEG.js 语法规则文件:

src/grammars/calculator.pegjs

@import "arithmetic";

start
  = additive

src/grammars/arithmetic.pegjs

@namespace myGrammar

additive
  = left:multiplicative _ "+" _ right:additive
  { return left + right; }
  / multiplicative

multiplicative
  = left:atomic _ "*" _ right:multiplicative
  { return left * right; }
  / atomic

atomic
  = "(" _ expr:additive _ ")" _ { return expr; }
  / n:number _ { return n; }

number = digits:[0-9]+ {
  return parseInt(digits.join(""));
}

_ "optional whitespace"
  = [ \t\n\r]*

我们还需要一个入口文件,用于调用 JavaScript 语法解析器。

src/index.js

import { parser } from './parser.js';

const input = '(2 + 3) * 4';
const result = parser.parse(input);
console.log(`${input} = ${result}`);

在以上代码中,我们导入了 JavaScript 语法解析器,将字符串 (2 + 3) * 4 传递给它,并将返回结果打印到控制台中。

在 package.json 文件中的 scripts 中添加如下命令:

{
  "scripts": {
    "build-parser": "pegjs src/grammars/calculator.pegjs dist/parser.js",
    "build": "yarn build-parser && webpack --config webpack.config.js",
    "dev": "webpack-dev-server --config webpack.config.js"
  }
}

然后,在命令行中运行如下命令:

npm run build
npm run dev

即可在浏览器中打开一个计算器应用,输入算式并得到结果。

结论

使用 pegjs-import-loader,我们可以方便地将多个 PEG.js 语法规则文件整合到一个文件中,极大地提高了代码的可维护性和可扩展性。同时,使用 PEG.js 编写语法解析器比使用传统的 LL(k) 解析器更简单和直观,因为 PEG.js 语法规则文件即是语法解析器。

希望本文对读者们理解和掌握 pegjs-import-loader 的使用方法和原理有所帮助。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/60067381890c4f72775842a5


纠错反馈