当前位置: 首页 > 工具软件 > Jison > 使用案例 >

从零开始写一个Jison解析器(1/10):Jison,不是Json

甄云
2023-12-01

从零开始写一个Jison解析器(1/10):Jison,不是Json

标题没有写错,Jison,不是Json

JSON(JavaScript Object Notation)是源自JavaScript的轻量级数据交换格式,既便于人类读写,也易于机器解析和生成。JSON基于Standard ECMA-262 3rd Edition - December 1999的一个子集。因此名字中包含JavaScript,不过JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。

JisonJavaScript解析器生成器(parser generator)。

什么是解析器(parser)?

解析器生成器(parser generator)?听起来有点拗口,要理解为什么Jison被称作解析器生成器(parser generator),还是从JSON说起。这是一个JSON例子。

{
  "object" : {
    "number" : 3.1415926,
    "string" : "This is a string in an object."
  },
  "array" : [
    "First value of array",
    "Second value of array",
    "Third value of array"
  ]
}

JavaScript中可以直接输出JSON

console.log({
  "object" : {
    "number" : 3.1415926,
    "string" : "This is a string in an object."
  },
  "array" : [
    "First value of array",
    "Second value of array",
    "Third value of array"
  ]
});

如果是字符串的话,那么就只能输出字符串了。

console.log(`{
  "object" : {
    "number" : 3.1415926,
    "string" : "This is a string in an object."
  },
  "array" : [
    "First value of array",
    "Second value of array",
    "Third value of array"
  ]
}`);

此时可以使用JSON.parse函数把字符串解析成JSON

console.log(JSON.parse(`{
  "object" : {
    "number" : 3.1415926,
    "string" : "This is a string in an object."
  },
  "array" : [
    "First value of array",
    "Second value of array",
    "Third value of array"
  ]
}`));

这里使用的JSON.parse函数就是解析器(parser),函数名称即为此意。

那么解析器(parser)和解析器生成器(parser generator)有什么区别和联系呢?

JSON.parse函数只能用于解析格式为JSON的字符串,如果字符串格式不是JSON,甚至于略有变化,例如在JSON中像写程序一样增加注释。

console.log(JSON.parse(`{
  //this is a comment line
  "object" : {
    "number" : 3.1415926,
    "string" : "This is a string in an object."
  },
  "array" : [
    "First value of array",
    "Second value of array",
    "Third value of array"
  ]
}`));

就会报错

SyntaxError: Unexpected token / in JSON at position 4

这是因为JSON.parse函数不能识别新增的//this is a comment line,此时就需要使用JSON5

const JSON5 = require('json5')
console.log(JSON5.parse(`{
  //this is a comment line
  "object" : {
    "number" : 3.1415926,
    "string" : "This is a string in an object."
  },
  "array" : [
    "First value of array",
    "Second value of array",
    "Third value of array"
  ]
}`));

这里用到的JSON5.parse函数,就是JSON5提供的解析器(parser),不过JSON5.parse函数也只能识别符合JSON5规范的字符串。类似的还有HjsonHOCON,都是JSON变体解析器(parser),每个解析器只能解析符合自己格式规范的语法。

前面提到JSON(JavaScript Object Notation)是轻量级数据交换格式,既便于人类读写,也易于机器解析和生成。类似的人类可读(非二进制)数据交换格式还有RDF(Resource Description Framework)、XML(eXtensible Markup Language)、Atom(基于XML)、YAML(是YAML Ain’t Markup Language的递归式缩写)、EDN(Extensible Data Notation)、Property listTOML(Tom’s Obvious, Minimal Language)、Rebol(Relative Expression Based Object Language)、Gellish(Generic Engineering Language)。

这些格式都有相应的解析器(parser),类似于前面JSON中添加注释的例子,也都有各自的缺点和局限性。例如使用前述这些成熟的格式,在几乎所有常用编程语言中都可以直接使用现成的解析器(parser),有时候还有多个解析器(parser)实现,不过在享受便利的同时,也要接受其全部缺点,例如YAML的第三版YAML 1.2的规格手册PDF版本有84页!而常见的YAML通常只有几十行,为了写对几十行YAML而去阅读84页手册未免得不偿失。然而当使用程序处理YAML时,如果不是使用成熟的程序包,而是自行解析的话,失误就在所难免,毕竟84页手册中描述的细节太多了。或者像JSON的各种变体解析器那样,需要对成熟的格式改进,当原有格式不支持这种改进时,也需要自行编写解析器(parser),此时也需要充分了解原有规范。进一步,如果要自定义格式,也需要专门编写解析器(parser)。

什么是解析器生成器(parser generator)?

前面提到了常见的几种需要自行编写解析器(parser)的场景以及面临的挑战,那么有没有办法能又快又好的开发一个解析器(parser)呢?也有一类成熟的产品,专门用于生成解析器(parser),这类产品就是解析器生成器(parser generator)。

 类似资料: