從零開始寫一個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成爲理想的數據交換語言。
而Jison是JavaScript解析器生成器(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規範的字符串。類似的還有Hjson、HOCON,都是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 list、TOML(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)。