lavats
lavats是一个由typescript写成的支持umd的DSL式的词法分析器、语法分析器库。
特色
- 支持typescript的
*.d.ts
文件 - 支持umd,可运行在浏览器和nodejs环境下
- 使用DSL式,可与js语言无缝衔接
- 支持左递归循环
安装
在命令行中输入:
npm install lavats
引入
cmd
var lavats = ;
amd
es6
;
<script>
使用
此处介绍了一些常用的类型,其他的具体类型信息,可以查看包内的*.d.ts
文件。
TerminalRule
用于生成终止符的规则
;// new TerminalRule(options: TerminalOptions | RegExp | string); // 可以接受正则表达式(不支持flags)/[0-9]+/; // 可以接受字符串"+"; // 可以接受TerminalOptions// interface TerminalOptions {// reg: RegExp | string; // 正则表达式或字符串// ignore?: boolean; // 是否忽略,默认为false// ast?: typeof TerminalAst; // 生成的ast类型,默认为TerminalAst// } reg: /\s+/ ignore: true ;
Lex
用于生成进行词法分析的Lex对象
- 一般用例:
; // new Lex(terminalRules: TerminalRule[]) let lex = /[0-9]+/ "+" "-" "*" "/" reg: /\s+/ ignore: true ; let result = lex; // interface LexResult {// ast: TerminalAst[]; // ast数组// errors: Token[]; // 未能识别的token// ignore: TerminalAst[]; // 被忽略的ast// } JSON; // =>// '{// "ast": [// { "name": "TerminalAst", "reg": "/[0-9]+/", "token": { "content": "100", "start": { "row": 0, "col": 0 }, "end": { "row": 0, "col": 3 } } },// { "name": "TerminalAst", "reg": "/\\*/", "token": { "content": "*", "start": { "row": 0, "col": 4 }, "end": { "row": 0, "col": 5 } } },// { "name": "TerminalAst", "reg": "/[0-9]+/", "token": { "content": "100", "start": { "row": 0, "col": 6 }, "end": { "row": 0, "col": 9 } } }// ],// "errors": [],// "ignore": [// { "name": "TerminalAst", "reg": "/\\s+/", "token": { "content": " ", "start": { "row": 0, "col": 3 }, "end": { "row": 0, "col": 4 } } },// { "name": "TerminalAst", "reg": "/\\s+/", "token": { "content": " ", "start": { "row": 0, "col": 5 }, "end": { "row": 0, "col": 6 } } }// ]// }'
- 含有无法识别的字符时:
; let lex = /[0-9]+/ "+" "-" "*" "/" reg: /\s+/ ignore: true ; let result = lex; JSON; // =>// '{// "ast": [// { "name": "TerminalAst", "reg": "/[0-9]+/", "token": { "content": "100", "start": { "row": 0, "col": 0 }, "end": { "row": 0, "col": 3 } } },// // 此处多出了'00'// { "name": "TerminalAst", "reg": "/[0-9]+/", "token": { "content": "00", "start": { "row": 0, "col": 4 }, "end": { "row": 0, "col": 6 } } },// { "name": "TerminalAst", "reg": "/\\*/", "token": { "content": "*", "start": { "row": 0, "col": 7 }, "end": { "row": 0, "col": 8 } } },// { "name": "TerminalAst", "reg": "/[0-9]+/", "token": { "content": "100", "start": { "row": 0, "col": 9 }, "end": { "row": 0, "col": 12 } } }// ],// "errors": [// // 此处多出了'.'// { "content": ".", "start": { "row": 0, "col": 3 }, "end": { "row": 0, "col": 4 } }// ], "ignore": [// { "name": "TerminalAst", "reg": "/\\s+/", "token": { "content": " ", "start": { "row": 0, "col": 6 }, "end": { "row": 0, "col": 7 } } },// { "name": "TerminalAst", "reg": "/\\s+/", "token": { "content": " ", "start": { "row": 0, "col": 8 }, "end": { "row": 0, "col": 9 } } }// ]// }'
StreamLex
用于生成进行词法分析的Lex对象,接受流式数据,以事件形式返回结果
; // new StreamLex(rules: TerminalRule[]) let lex = /[0-9]+/ "+" "-" "*" "/" reg: /\s+/ ignore: true ; lex;lex;lex;lex; lex;// ast:// { "name": "TerminalAst", "reg": "/[0-9]+/", "token": { "content": "100", "start": { "row": 0, "col": 0 }, "end": { "row": 0, "col": 3 } } } // error:// { "content": ".", "start": { "row": 0, "col": 3 }, "end": { "row": 0, "col": 4 } } // warning:此处并没有返回'00',因为并不知道'00'后面是否有其他的数字 lex;// ast:// { "name": "TerminalAst", "reg": "/[0-9]+/", "token": { "content": "00", "start": { "row": 0, "col": 4 }, "end": { "row": 0, "col": 6 } } } // ignore:// { "name": "TerminalAst", "reg": "/\\s+/", "token": { "content": " ", "start": { "row": 0, "col": 6 }, "end": { "row": 0, "col": 7 } } } lex;// ast:// { "name": "TerminalAst", "reg": "/\\*/", "token": { "content": "*", "start": { "row": 0, "col": 7 }, "end": { "row": 0, "col": 8 } } } // ignore:// { "name": "TerminalAst", "reg": "/\\s+/", "token": { "content": " ", "start": { "row": 0, "col": 8 }, "end": { "row": 0, "col": 9 } } } // warning:此处也并没有返回'100',理由同上 lex;// ast:// { "name": "TerminalAst", "reg": "/[0-9]+/", "token": { "content": "100", "start": { "row": 0, "col": 9 }, "end": { "row": 0, "col": 12 } } } // end
- 另有
reset
方法,用于重置StreamLex
对象
lex;
RuleCollection
用于生成语法分析器的对象
; { return +thistokencontent; } { return left + right; } { return left - right; } { return left * right; } { return left / right; } { return thischildren0; } { return thischildren1; } { return thischildren2; } { return thisoperator; } let collection = ; // 省略空格collection; // num => [0-9]+let num = collection; // add => "+"let add = collection // sub => "-"let sub = collection // mul => "*"let mul = collection // div => "/"let div = collection // 无特殊Ast对象的规则可以直接定义中间变量使用// operator => add | sub | mul | divlet operator = add; // 非终结符规则的定义需要分开两步(先声明,后定义)let expr = collection;// expr => num operator numexpr; // 获取语法分析器Parserlet parser = collection;let result = parser; // interface ParserResult<T> {// ast?: T; // 生成的ast树,可通过判断是否为undefined,来判断是否成功// ignoreAst: TerminalAst[]; // 被跳过的ast// errorAst: Ast[]; // 不符合语法规则的ast// errorToken: Token[]; // 不符合词法规则的token// } console;// {// "ast": {// "name": "Expr",// "children": [// { "name": "Num", "reg": "/[0-9]+/", "token": { "content": "100", "start": { "row": 0, "col": 0 }, "end": { "row": 0, "col": 3 } } },// { "name": "Mul", "reg": "/\\*/", "token": { "content": "*", "start": { "row": 0, "col": 4 }, "end": { "row": 0, "col": 5 } } },// { "name": "Num", "reg": "/[0-9]+/", "token": { "content": "100", "start": { "row": 0, "col": 6 }, "end": { "row": 0, "col": 9 } } }// ]// },// "ignoreAst": [// { "name": "TerminalAst", "reg": "/\\s+/", "token": { "content": " ", "start": { "row": 0, "col": 3 }, "end": { "row": 0, "col": 4 } } },// { "name": "TerminalAst", "reg": "/\\s+/", "token": { "content": " ", "start": { "row": 0, "col": 5 }, "end": { "row": 0, "col": 6 } } }// ],// "errorAst": [],// "errorToken": []// } let execResult = resultast;console; // 10000
另外有StreamParser,接受流式数据,以事件形式返回结果
let parser = collection;parser;parser;parser;parser;parser; parser;parser;// 200
提供便捷方法,可使用插值字符串的方式,来定义规则。
// operator => add | sub | mul | div// let operator = add.or(sub).or(mul).or(div);// 可换写成:let operator = Rulebnf` | | | `; // expr => num operator num// expr.define(num.and(operator).and(num));// 可换写成:exprdefineBnf` `;
StreamParser
可通过reset
方法重置
parser;