--- /dev/null
+docs/.*#*
+src/ch1/package-lock.json
+src/ch1/node_modules
\ No newline at end of file
所以我們可以定義以下的BNF風文法:
```
-Language ::= PrintTxt | Exprs
+Language ::= MainTxt | Exprs | Comment
-PrintTxt ::= (('\' '@')| 非@字元)+ //「我是一隻貓」或是「www\@example.com」
+Comment ::= '/*' (不含'*/'的任何字元組合)* '*/'
+
+MainTxt ::= (('\' '@')| 非@非空白字元)+ //顯示的文字。「我是一隻貓」或是「www\@example.com」
+
+// Exprs 表示一群定義變數、常數、函數、函數套用的表達式
Exprs ::= @ Expr* @ // *表示前面的重複0次以上(包含不出現)
-Expr ::= (Letting | Setting | Lambda | Apply | Var| Const) | "(" Expr ")"
+// Comment also included
+// "(" and ")" only for applying function
+Expr ::= (Letting | Setting | Lambda | | Var| Const) | "(" Applying ")" | Comment
Letting ::= "let" Var "=" Expr "in" Expr // let foo = 12 in ...
Setting ::= Var ":=" Expr "in" Expr // foo := a in ...
-Lambda ::= "fn" Var "->" Expr // fn x -> 12
+// we force every function have at least 1 argument.
+Lambda ::= "fn" LambdaArgs "->" Expr // fn x y -> 12
+
+LambdaArgs ::= Var | Var LambdaArgs
-Apply ::= Expr Expr // foo 3 即foo(3)
+Applying ::= Expr ExprArgs // foo 3 9 即foo(3, 9)
+
+ExprArgs ::= Expr | (Expr ExprArgs)
Var ::= ID
-Const ::= String | Float | Int
+Const ::= String | Float | Integer
ID ::= ("_" | [a-z] | [A-Z]) ("_" | [0-9] | [a-z] | [A-Z])+
String ::= '"' (不是「"」的任一字元|('\' '"')) '"'
```
-## 用ParserCombinator進行tokenize
+而上述的item可以被1個以上半形空白或tab(`\t`)以及1個「`\n`或`\r\n`」(換行符號)隔開。而為求簡化這些符號在MainTxt均指代一個半形空白。也就是空一個半形空白、兩個半形空白、一個tab、一個換行符號等等都會顯示如一個半形符號。而在Expr表達式區,把它忽略掉。另外兩個換行符號設定為換行指令,而這在Expr區會被忽略。所以要加另外兩條:
+
+```
+Space = (' ' | '\t')* | '\n' | '\r\n'
+NewPara = = ('\n' |'\r' '\n' ) ('\n' |'\r' '\n' )
+```
+
+## 用ts-parsec和regexp進行tokenize
Parser combinator(分析器組合子)是一種利用高階函數來簡化分析器撰寫的辦法。這講到頭來會涉及「遞歸下降分析」以及其他編譯理論的東西,但太難了(聽說可以讀編譯理論的「龍書我們可以製作一個小的tokenizer。但是因為自己寫parser combinator太累了,所以我們就用nom來幫我們代勞。
」)。講一個簡單的案例吧:
}
```
-假設我們要將字串`s`的前3個字的match 0~9呢?如果會高階函數的話,引入一個`then`函數,然後把`match0to9`傳進去,這樣寫起來比較簡潔,行數可以比較少:
+假設我們要將字串`s`的前3個字的match 0~9呢?如果會高階函數的話,引入一個`then`函數,然後把`match0to9`傳進去,這樣寫起來比較不會太糾結,比較好維護:
```
function thenDo(input, fun){
安裝`ts-parsec`可以用:`npm install -g typescript-parsec`。底下的程式使用的函數的詳細說明可以參考[官方文件](https://github.com/microsoft/ts-parsec/blob/master/doc/ParserCombinators.md)。
-假設我們要match 0-9任意次以上(就是integer),我們可以這樣寫:
+因為這個軟體在 tokenize 的時候使用regex,所以我們就用這個東西來處理。
+
+我們編輯Node.js的進入點程式(假設為src/index.js`),底下為定義tokenizer的型別和regex pattern:
+
+```typescript
+/** the type of token */
+enum TokenKind {
+ Int, // 3
+ Flo, // 3.1416
+ Id, // foo, _123, etc
+ At, // @
+ Comt, // comment /*
+ Str, /** "foo" */
+ Assign, /** = */
+ Set, /** := */
+ Keyword, /** let, in */
+ LParen, /** ( */
+ RParen, /** ) */
+ Space, /** semi-width space tab, \r\n? */
+ NewPara, /** breaking paragraph, (\r\n?){2} */
+ MainTxt, /** used in main text */
+}
+
+// tokenizer
+const tokenizer = parsec.buildLexer([
+ [true, /^\d+/g, TokenKind.Int],
+ [true, /^\d+\.\d+/g, TokenKind.Flo],
+ [true, /^(let|in)/g, TokenKind.Keyword], // let and in
+ [true, /^[_a-zA-Z][_0-9a-zA-Z]*/g, TokenKind.Id],
+ [true, /^\@/g, TokenKind.At],
+ /* inside comment, only accept 1. non / character
+ or 2. "/ + non * character" */
+ [true, /^\/\*(\/[^*]|[^\\]?)*\*\//g, TokenKind.Comt],
+ [true, /^\"(\\\"|[^\"]?)*\"/g, TokenKind.Str],
+ [true, /^\:\=/g, TokenKind.Set],
+ [true, /^\=/g, TokenKind.Assign],
+ [true, /^\(/g, TokenKind.LParen],
+ [true, /^\)/g, TokenKind.RParen],
+ [true, /^([ \t]+|\n)/g, TokenKind.Space],
+ [true, /^(\r?\n){2}/g, TokenKind.NewPara],
+ [true, /^(\\\@|[^@\s])+/g, TokenKind.MainTxt],
+]);
```
-// import all the parser unit for string
-use nom::character::complete::*;
-// for the return type
-use nom::IResult;
+### 常數parsing
+
+增加儲存實際變數值的`ASTNode`型別
-// integer ::= [0-9]+
-pub fn integer(input: &str) -> IResult<&str, &str> {
- return digit1(input) ; // [0-9]+
+```typescript
+// add "actualValue" in the parsed Token
+export interface ASTNode extends parsec.Token<TokenKind>{
+ // number is for float number;
+ //it's optional. since keyword has no value
+ actualValue? : bigint | number | string;
}
+```
-// test parser
-#[cfg(test)]
-mod tests {
- // import the functions ouside mod tests
- use super::*;
-
- // test integer
- #[test]
- fn test_integer() {
- //if no error is shown, the function passes the test
- assert_eq!(integer("12345"), Ok(("", "12345")));
- assert_eq!(integer("0"), Ok(("", "0")));
- }
+增加處理常數的parser。`...value`有擴充object的意思。
+```typescript
+function applyInteger(value: parsec.Token<TokenKind.Int>): ASTNode {
+ // extend value to ASTNode
+ const newNode : ASTNode = {
+ actualValue : BigInt(value.text) ,
+ ...value};
+ return newNode;
}
+function applyFloat(value: parsec.Token<TokenKind.Flo>): ASTNode {
+ // extend value to ASTNode
+ const newNode : ASTNode = {
+ actualValue : parseFloat(value.text) ,
+ ...value};
+ return newNode;
+}
+function applyString(value: parsec.Token<TokenKind.Str>): ASTNode {
+ // extend value to ASTNode
+ const newNode : ASTNode = {
+ // get only text[1,2,...,the second last char]
+ actualValue : value.text.slice(1,value.text.length-1).replace(/\\\"/g, "\"") ,
+ ...value};
+ return newNode;
+}
```
-用`cargo run`可以順利通過:
+製作`CONST`這個parser,然後再加上rule:
+
+```typescript
+const CONST = parsec.rule<TokenKind, ASTNode>();
+/*
+CONST ::= INT | FLOAT | STRING
+*/
+CONST.setPattern(
+ parsec.alt(
+ parsec.apply(parsec.tok(TokenKind.Int), applyInteger),
+ parsec.apply(parsec.tok(TokenKind.Flo), applyFloat),
+ parsec.apply(parsec.tok(TokenKind.Str), applyString),
+ )
+);
```
-running 1 test
-test tests::test_integer ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
-```
-
-我們做第二個tokenizer,`float`:
+最後包起來進行測試:
-其中的`recognize`蒐集所有包在裡面的`parsers`的string。
-```
-// collect matched strings of all the parsers,
-use nom::combinator::recognize;
-// given 2 parser and gets the result as (1st_matched, 2nd_matched),
-use nom::sequence::pair;
-// exact matching characters
-use nom::bytes::complete::tag;
-
-// float ::= [0-9]+ "." [0-9]+
-pub fn float(input: &str) -> IResult<&str, &str>{
- // [0-9]+ "." [0-9]+
- // "12.345" returns Ok((else, (("12", '.'), "345"))), then recgonize them as
- // Ok("12.345")
- let a =
- recognize(pair(pair(digit1, tag(".")), digit1))(input);
- return a;
+```typescript
+function mainParse(inputStr : string){
+ return parsec.expectSingleResult(parsec.expectEOF(
+ CONST.parse(tokenizer.parse(inputStr))));
}
-```
-parser `identifier`(引用的函數的名稱空間略)。使用`fold_may0`和新的空vector來儲存match多次的parser的符合結果:
+// test
+function main(){
+ // bigint has suffix `n`
+ assert.strictEqual(mainParse('123455667').actualValue, 123455667n);
+ assert.strictEqual(mainParse('000').actualValue, 0n);
+ assert.strictEqual(mainParse('1.22').actualValue, 1.22);
+ assert.strictEqual(mainParse('0.0').actualValue, 0.0);
+ assert.strictEqual(mainParse(`""`).actualValue, "");
+ assert.strictEqual(mainParse(`"the little town"`).actualValue, `the little town`);
+ assert.strictEqual(mainParse(`"\\\"Alice\\\""`).actualValue, `"Alice"`);
+
+
+};
```
-pub fn identifier(input : &str) -> IResult<&str, &str>{
- return recognize(pair(
- // 1st character is a-z, A-Z or _
- satisfy(|c| (is_alphabetic(c as u8) || c == '_')),
- // the tail characters (0+ times matched) storing in a vector
- fold_many0(
- // a-z, A-Z, 0-9, _
- satisfy(|c| (is_alphanumeric(c as u8) || c == '_')),
- // initial vector
- Vec::new,
- // once it matches, append the matched item to the vector.
- |mut acc: Vec<_>, item| {
- acc.push(item);
- acc
- }
- )))(input);
-
-}
+### 表達式
+定義`AST型別`:
+
+```type AST = AST[] | ASTNode;
```
+
## 平面操作
### 基本函數與直譯器
--- /dev/null
+{
+ "name": "ch1",
+ "version": "0.0.1",
+ "description": "little typesetting draught",
+ "main": "src/index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "typesetting",
+ "pdf"
+ ],
+ "author": "Tan Kian-ting",
+ "license": "MIT",
+ "dependencies": {
+ "typescript-parsec": "^0.3.4"
+ },
+ "devDependencies": {
+ "@typescript-eslint/eslint-plugin": "^6.13.2",
+ "@typescript-eslint/parser": "^6.13.2",
+ "tslint": "^6.1.3",
+ "@types/node": "^20.10.4"
+ }
+}
--- /dev/null
+import * as parsec from 'typescript-parsec';
+/** the type of token */
+declare enum TokenKind {
+ Int = 0,
+ Flo = 1,
+ Id = 2,
+ At = 3,
+ Comt = 4,
+ Str = /** "foo" */ 5,
+ Lambda = /** -> */ 6,
+ Assign = /** = */ 7,
+ Set = /** := */ 8,
+ Keyword = /** let, in */ 9,
+ LParen = /** ( */ 10,
+ RParen = /** ) */ 11,
+ Space = /** semi-width space tab, \r\n? */ 12,
+ NewPara = /** breaking paragraph, (\r\n?){2} */ 13,
+ MainTxt = /** used in main text */ 14
+}
+export interface ASTNode extends parsec.Token<TokenKind> {
+ actualValue?: bigint | number | string;
+}
+/** AST Tree */
+declare type AST = AST[] | ASTNode;
+/** from AST to S-exp */
+export declare function astToSExp(ast: AST): any;
+export {};
--- /dev/null
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.astToSExp = void 0;
+const parsec = require("typescript-parsec"); // import parsec
+/* for test */
+const assert = require("assert");
+/** the type of token */
+var TokenKind;
+(function (TokenKind) {
+ TokenKind[TokenKind["Int"] = 0] = "Int";
+ TokenKind[TokenKind["Flo"] = 1] = "Flo";
+ TokenKind[TokenKind["Id"] = 2] = "Id";
+ TokenKind[TokenKind["At"] = 3] = "At";
+ TokenKind[TokenKind["Comt"] = 4] = "Comt";
+ TokenKind[TokenKind["Str"] = 5] = "Str";
+ TokenKind[TokenKind["Lambda"] = 6] = "Lambda";
+ TokenKind[TokenKind["Assign"] = 7] = "Assign";
+ TokenKind[TokenKind["Set"] = 8] = "Set";
+ TokenKind[TokenKind["Keyword"] = 9] = "Keyword";
+ TokenKind[TokenKind["LParen"] = 10] = "LParen";
+ TokenKind[TokenKind["RParen"] = 11] = "RParen";
+ TokenKind[TokenKind["Space"] = 12] = "Space";
+ TokenKind[TokenKind["NewPara"] = 13] = "NewPara";
+ TokenKind[TokenKind["MainTxt"] = 14] = "MainTxt";
+})(TokenKind || (TokenKind = {}));
+/** from AST to S-exp */
+function astToSExp(ast) {
+ // if it's an array
+ if (Array.isArray(ast)) {
+ return "(" + ast.map((x) => astToSExp(x)).join(" ") + ")";
+ // if it's a item
+ }
+ else {
+ return ast.text;
+ }
+}
+exports.astToSExp = astToSExp;
+// tokenizer
+const tokenizer = parsec.buildLexer([
+ [true, /^\d+/g, TokenKind.Int],
+ [true, /^\d+\.\d+/g, TokenKind.Flo],
+ [true, /^(let|in|fn)/g, TokenKind.Keyword],
+ [true, /^[_a-zA-Z][_0-9a-zA-Z]*/g, TokenKind.Id],
+ [true, /^\@/g, TokenKind.At],
+ /* inside comment, only accept 1. non / character
+ or 2. "/ + non * character" */
+ [true, /^\/\*(\/[^*]|[^\\]?)*\*\//g, TokenKind.Comt],
+ [true, /^\"(\\\"|[^\"]?)*\"/g, TokenKind.Str],
+ [true, /^\:\=/g, TokenKind.Set],
+ [true, /^\=/g, TokenKind.Assign],
+ [true, /^->/g, TokenKind.Lambda],
+ [true, /^\(/g, TokenKind.LParen],
+ [true, /^\)/g, TokenKind.RParen],
+ [true, /^([ \t]+|[ \t]*\r?\n[ \t]*)/g, TokenKind.Space],
+ [true, /^(\r?\n){2}/g, TokenKind.NewPara],
+ [true, /^(\\\@|[^@\s])/g, TokenKind.MainTxt],
+]);
+/** ignore spaces ,new lines, and comments */
+const _ = parsec.opt(parsec.alt(parsec.tok(TokenKind.Space), parsec.tok(TokenKind.NewPara),
+// space or newPara + comment + space or newPara
+parsec.seq(parsec.opt(parsec.alt(parsec.tok(TokenKind.Space), parsec.tok(TokenKind.NewPara))), parsec.tok(TokenKind.Comt), parsec.opt(parsec.alt(parsec.tok(TokenKind.Space), parsec.tok(TokenKind.NewPara))))));
+function applyInteger(value) {
+ // extend value to ASTNode
+ const newNode = {
+ actualValue: BigInt(value.text),
+ ...value
+ };
+ return newNode;
+}
+function applyFloat(value) {
+ const newNode = {
+ actualValue: parseFloat(value.text),
+ ...value
+ };
+ return newNode;
+}
+function applyString(value) {
+ const newNode = {
+ // get only text[1,2,...,the second last char]
+ actualValue: value.text.slice(1, value.text.length - 1).replace(/\\\"/g, "\""),
+ ...value
+ };
+ return newNode;
+}
+function applyIdentifier(value) {
+ const newNode = {
+ actualValue: value.text,
+ ...value
+ };
+ return newNode;
+}
+/** apply LETTING.
+ * returns [let, [var, x], expr] */
+function applyLetting(input) {
+ // node representing let
+ let letNode = input[0];
+ let varNode = input[2];
+ let valueNode = input[6];
+ let exprAST = input[10];
+ return [letNode, [varNode, valueNode], exprAST];
+}
+/** apply SETTING */
+function applySetting(input) {
+ // node representing let
+ let setNode = input[2];
+ let varNode = input[0];
+ let valueNode = input[4];
+ let exprAST = input[8];
+ // (:= (var val) expr) : set var = val in expr
+ return [setNode, [varNode, valueNode], exprAST];
+}
+function applyLambda(input) {
+ let lambdaNode = input[0];
+ let argHead = input[1];
+ let argTail = input[2];
+ let body = input[6];
+ let args = [argHead].concat(argTail);
+ // return (fn (args) body) like lambda in Scheme
+ return [lambdaNode, args, body];
+}
+function applyApplying(input) {
+ let applier = input[0];
+ let applieeHead = input[2];
+ let applieeTail = input[3];
+ let appliee = [(applieeHead)].concat(applieeTail);
+ // foo 2 3 => (foo (2 3))
+ return [applier, appliee];
+}
+/** define all the parser sentence */
+const CONST = parsec.rule();
+const VAR = parsec.rule();
+const ARG = parsec.rule();
+const EXPR = parsec.rule();
+const LETTING = parsec.rule();
+const SETTING = parsec.rule();
+const LAMBDA = parsec.rule();
+const APPLYING = parsec.rule();
+/*
+CONST ::= INT | FLOAT | STRING
+*/
+CONST.setPattern(parsec.alt(parsec.apply(parsec.tok(TokenKind.Int), applyInteger), parsec.apply(parsec.tok(TokenKind.Flo), applyFloat), parsec.apply(parsec.tok(TokenKind.Str), applyString)));
+/** VAR = ID */
+VAR.setPattern(parsec.apply(parsec.tok(TokenKind.Id), applyIdentifier));
+/** ARG = ID */
+ARG.setPattern(parsec.apply(parsec.tok(TokenKind.Id), applyIdentifier));
+/**SETTING ::= VAR ":=" EXPR in EXPR
+ * and ignore the spaces and new lines with `_`
+*/
+SETTING.setPattern(parsec.apply(parsec.seq(VAR, _, parsec.str(":="), _, EXPR, _, parsec.str("in"), _, EXPR), applySetting));
+/**LETTING ::= "let" VAR "=" EXPR in EXPR
+ * and ignore the spaces and new lines with `_`
+*/
+LETTING.setPattern(parsec.apply(parsec.seq(parsec.str("let"), _, VAR, _, parsec.str("="), _, EXPR, _, parsec.str("in"), _, EXPR), applyLetting));
+/**LAMBDA ::= "fn" (Args)+ "->" EXPR
+ * and ignore the spaces and new lines with `_`
+*/
+LAMBDA.setPattern(parsec.apply(parsec.seq(parsec.str("fn"), parsec.kright(_, ARG), // arg SpaceNL
+parsec.rep_sc(parsec.kright(_, ARG)), //other (arg SpaceNL), repeat 0+times
+_, parsec.str("->"), _, EXPR), applyLambda));
+// APPLYING = ( "(" APPLYING ")" |LAMBDA|VAR) APPLIEE+
+APPLYING.setPattern(parsec.apply(parsec.seq(parsec.alt(LAMBDA, VAR, parsec.kmid(parsec.seq(parsec.str('('), _), APPLYING, parsec.seq(_, parsec.str(')')))), _, EXPR, parsec.rep_sc(parsec.kright(_, EXPR))), applyApplying));
+/** EXPR = CONST | VAR
+ * | LETTING | SETTING
+ * | LAMBDA | APPLYING
+ * | "(" APPLYING ")" */
+EXPR.setPattern(parsec.alt(CONST, VAR, LETTING, SETTING, LAMBDA, parsec.kmid(parsec.seq(parsec.str('('), _), APPLYING, parsec.seq(_, parsec.str(')')))));
+function mainParse(inputStr) {
+ return parsec.expectSingleResult(parsec.expectEOF(EXPR.parse(tokenizer.parse(inputStr))));
+}
+// test
+function main() {
+ // bigint has suffix `n`
+ assert.strictEqual(mainParse('123455667').actualValue, 123455667n);
+ assert.strictEqual(mainParse('000').actualValue, 0n);
+ assert.strictEqual(mainParse('1.22').actualValue, 1.22);
+ assert.strictEqual(mainParse('0.0').actualValue, 0.0);
+ assert.strictEqual(mainParse(`""`).actualValue, "");
+ assert.strictEqual(mainParse(`"the little town"`).actualValue, `the little town`);
+ assert.strictEqual(mainParse(`"\\\"Alice\\\""`).actualValue, `"Alice"`);
+ assert.strictEqual(mainParse(`foo`).actualValue, "foo");
+ assert.strictEqual(astToSExp(mainParse(`let x = 12 in 23`)), "(let (x 12) 23)");
+ assert.strictEqual(astToSExp(mainParse(`let y = 10 in let x = 12 in 23`)), "(let (y 10) (let (x 12) 23))");
+ assert.strictEqual(astToSExp(mainParse(`let y = 10 in y := 12 in 23`)), "(let (y 10) (:= (y 12) 23))");
+ assert.strictEqual(astToSExp(mainParse(`fn x y -> 234`)), "(fn (x y) 234)");
+ assert.strictEqual(astToSExp(mainParse(`(add 12 23 )`)), "(add (12 23))");
+ assert.strictEqual(astToSExp(mainParse(`(foo x y)`)), "(foo (x y))");
+ assert.strictEqual(astToSExp(mainParse(`((foo 6 7) bar)`)), "((foo (6 7)) (bar))");
+ assert.strictEqual(astToSExp(mainParse(`fn x y ->
+ /* foo bar */
+ (foo x y)`)), "(fn (x y) (foo (x y)))");
+}
+;
+main();
+//# sourceMappingURL=index.js.map
\ No newline at end of file
--- /dev/null
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
--- /dev/null
+import * as parsec from 'typescript-parsec'; // import parsec
+/* for test */
+import * as assert from 'assert';
+
+/** the type of token */
+enum TokenKind {
+ Int, // 3
+ Flo, // 3.1416
+ Id, // foo, _123, etc
+ At, // @
+ Comt, // comment /*
+ Str, /** "foo" */
+ Lambda, /** -> */
+ Assign, /** = */
+ Set, /** := */
+ Keyword, /** let, in */
+ LParen, /** ( */
+ RParen, /** ) */
+ Space, /** semi-width space tab, \r\n? */
+ NewPara, /** breaking paragraph, (\r\n?){2} */
+ MainTxt, /** used in main text */
+}
+
+// add "actualValue" in the parsed Token
+export interface ASTNode extends parsec.Token<TokenKind>{
+ // number is for float number;
+ //it's optional. since keyword has no value
+ actualValue? : bigint | number | string;
+}
+
+/** AST Tree */
+type AST = AST[] | ASTNode;
+
+/** from AST to S-exp */
+export function astToSExp(ast : AST){
+ // if it's an array
+ if (Array.isArray(ast)){
+ return "(" + ast.map((x : AST)=>astToSExp(x)).join(" ") + ")";
+ // if it's a item
+ }else{
+ return ast.text;
+ }
+}
+
+
+// tokenizer
+const tokenizer = parsec.buildLexer([
+ [true, /^\d+/g, TokenKind.Int],
+ [true, /^\d+\.\d+/g, TokenKind.Flo],
+ [true, /^(let|in|fn)/g, TokenKind.Keyword], // let, in, fn
+ [true, /^[_a-zA-Z][_0-9a-zA-Z]*/g, TokenKind.Id],
+ [true, /^\@/g, TokenKind.At],
+ /* inside comment, only accept 1. non / character
+ or 2. "/ + non * character" */
+ [true, /^\/\*(\/[^*]|[^\\]?)*\*\//g, TokenKind.Comt],
+ [true, /^\"(\\\"|[^\"]?)*\"/g, TokenKind.Str],
+ [true, /^\:\=/g, TokenKind.Set],
+ [true, /^\=/g, TokenKind.Assign],
+ [true, /^->/g, TokenKind.Lambda],
+ [true, /^\(/g, TokenKind.LParen],
+ [true, /^\)/g, TokenKind.RParen],
+ [true, /^([ \t]+|[ \t]*\r?\n[ \t]*)/g, TokenKind.Space],
+ [true, /^(\r?\n){2}/g, TokenKind.NewPara],
+ [true, /^(\\\@|[^@\s])/g, TokenKind.MainTxt],
+]);
+
+
+/** ignore spaces ,new lines, and comments */
+const _ = parsec.opt(parsec.alt(
+ parsec.tok(TokenKind.Space),
+ parsec.tok(TokenKind.NewPara),
+
+ // space or newPara + comment + space or newPara
+ parsec.seq(
+ parsec.opt(parsec.alt(
+ parsec.tok(TokenKind.Space),
+ parsec.tok(TokenKind.NewPara))),
+ parsec.tok(TokenKind.Comt),
+ parsec.opt(parsec.alt(
+ parsec.tok(TokenKind.Space),
+ parsec.tok(TokenKind.NewPara))),
+ )
+ )
+);
+
+
+
+
+function applyInteger(value: parsec.Token<TokenKind.Int>): ASTNode {
+ // extend value to ASTNode
+ const newNode : ASTNode = {
+ actualValue : BigInt(value.text) ,
+ ...value};
+ return newNode;
+}
+
+function applyFloat(value: parsec.Token<TokenKind.Flo>): ASTNode {
+ const newNode : ASTNode = {
+ actualValue : parseFloat(value.text) ,
+ ...value};
+ return newNode;
+}
+
+function applyString(value: parsec.Token<TokenKind.Str>): ASTNode {
+ const newNode : ASTNode = {
+ // get only text[1,2,...,the second last char]
+ actualValue : value.text.slice(1,value.text.length-1).replace(/\\\"/g, "\"") ,
+ ...value};
+ return newNode;
+}
+
+function applyIdentifier(value: parsec.Token<TokenKind.Id>): ASTNode {
+ const newNode : ASTNode = {
+ actualValue : value.text,
+ ...value};
+ return newNode;
+}
+
+/** apply LETTING.
+ * returns [let, [var, x], expr] */
+function applyLetting(input: [parsec.Token<TokenKind>, // let
+ parsec.Token<TokenKind> | undefined, // space
+ ASTNode, // var
+ parsec.Token<TokenKind>| undefined, // space
+ parsec.Token<TokenKind>, // =
+ parsec.Token<TokenKind>| undefined, // space
+ AST, // val
+ parsec.Token<TokenKind>| undefined, // space
+ parsec.Token<TokenKind>, // in
+ parsec.Token<TokenKind>| undefined, // space
+ AST // expr
+ ]): AST {
+ // node representing let
+ let letNode : ASTNode = input[0];
+ let varNode = input[2];
+ let valueNode = input[6];
+ let exprAST = input[10];
+
+ return [letNode, [varNode, valueNode], exprAST];
+
+}
+
+/** apply SETTING */
+function applySetting(input: [ASTNode, // var
+ parsec.Token<TokenKind>| undefined, // space
+ parsec.Token<TokenKind>, // :=
+ parsec.Token<TokenKind>| undefined, // space
+ AST, // val
+ parsec.Token<TokenKind>| undefined, // space
+ parsec.Token<TokenKind>, // in
+ parsec.Token<TokenKind>| undefined, // space
+ AST // expr
+ ]): AST {
+ // node representing let
+ let setNode = input[2];
+ let varNode = input[0];
+ let valueNode = input[4];
+ let exprAST = input[8];
+
+ // (:= (var val) expr) : set var = val in expr
+ return [setNode, [varNode, valueNode], exprAST];
+
+}
+
+function applyLambda(input: [ASTNode, // fn
+ ASTNode, // arg
+ ASTNode[], // args
+ parsec.Token<TokenKind>| undefined, // space
+ parsec.Token<TokenKind>, // ->
+ parsec.Token<TokenKind>| undefined, // space
+ AST // expr
+]): AST {
+ let lambdaNode = input[0];
+ let argHead = input[1];
+ let argTail = input[2];
+ let body = input[6];
+ let args = [argHead].concat(argTail)
+
+ // return (fn (args) body) like lambda in Scheme
+ return [lambdaNode, args, body];
+}
+
+
+function applyApplying(input : [ASTNode, // caller
+ parsec.Token<TokenKind> |undefined, // space
+ ASTNode, // head of callee
+ AST[] // tail of callee
+ ]){
+ let applier = input[0];
+ let applieeHead = input[2];
+ let applieeTail = input[3];
+ let appliee = [<AST>(applieeHead)].concat(applieeTail);
+
+
+ // foo 2 3 => (foo (2 3))
+ return [applier, appliee];
+
+}
+
+/** define all the parser sentence */
+const CONST = parsec.rule<TokenKind, ASTNode>();
+const VAR = parsec.rule<TokenKind, ASTNode>();
+const ARG = parsec.rule<TokenKind, ASTNode>();
+const EXPR = parsec.rule<TokenKind, AST>();
+const LETTING = parsec.rule<TokenKind, AST>();
+const SETTING = parsec.rule<TokenKind, AST>();
+const LAMBDA = parsec.rule<TokenKind, AST>();
+const APPLYING = parsec.rule<TokenKind, AST>();
+
+
+
+/*
+CONST ::= INT | FLOAT | STRING
+*/
+CONST.setPattern(
+ parsec.alt(
+ parsec.apply(parsec.tok(TokenKind.Int), applyInteger),
+ parsec.apply(parsec.tok(TokenKind.Flo), applyFloat),
+ parsec.apply(parsec.tok(TokenKind.Str), applyString),
+ )
+);
+
+/** VAR = ID */
+VAR.setPattern(
+ parsec.apply(parsec.tok(TokenKind.Id), applyIdentifier),
+);
+
+/** ARG = ID */
+ARG.setPattern(
+ parsec.apply(parsec.tok(TokenKind.Id), applyIdentifier),
+);
+
+
+
+
+/**SETTING ::= VAR ":=" EXPR in EXPR
+ * and ignore the spaces and new lines with `_`
+*/
+
+SETTING.setPattern(
+ parsec.apply(
+ parsec.seq(
+ VAR,
+ _,
+ parsec.str(":="),
+ _,
+ EXPR,
+ _,
+ parsec.str("in"),
+ _,
+ EXPR), applySetting));
+
+/**LETTING ::= "let" VAR "=" EXPR in EXPR
+ * and ignore the spaces and new lines with `_`
+*/
+LETTING.setPattern(
+ parsec.apply(
+ parsec.seq(
+ parsec.str("let"),
+ _,
+ VAR,
+ _,
+ parsec.str("="),
+ _,
+ EXPR,
+ _,
+ parsec.str("in"),
+ _,
+ EXPR), applyLetting));
+
+
+
+/**LAMBDA ::= "fn" (Args)+ "->" EXPR
+ * and ignore the spaces and new lines with `_`
+*/
+LAMBDA.setPattern(
+ parsec.apply(
+ parsec.seq(
+ parsec.str("fn"),
+ parsec.kright(_, ARG), // arg SpaceNL
+ parsec.rep_sc(parsec.kright(_, ARG)), //other (arg SpaceNL), repeat 0+times
+ _,
+ parsec.str("->"),
+ _,
+ EXPR),
+ applyLambda)
+)
+
+// APPLYING = ( "(" APPLYING ")" |LAMBDA|VAR) APPLIEE+
+APPLYING.setPattern(
+ parsec.apply(
+ parsec.seq(
+ parsec.alt(
+ LAMBDA,
+ VAR,
+ parsec.kmid(
+ parsec.seq(parsec.str('('), _),
+ APPLYING,
+ parsec.seq(_, parsec.str(')')))
+ ),
+ _,
+ EXPR,
+ parsec.rep_sc(parsec.kright(_, EXPR))),
+ applyApplying));
+
+/** EXPR = CONST | VAR
+ * | LETTING | SETTING
+ * | LAMBDA | APPLYING
+ * | "(" APPLYING ")" */
+EXPR.setPattern(
+ parsec.alt(
+ CONST,
+ VAR,
+ LETTING,
+ SETTING,
+ LAMBDA,
+ parsec.kmid(
+ parsec.seq(parsec.str('('), _),
+ APPLYING,
+ parsec.seq(_, parsec.str(')')))
+ )
+);
+
+
+
+
+
+function mainParse(inputStr : string){
+ return parsec.expectSingleResult(parsec.expectEOF(
+ EXPR.parse(tokenizer.parse(inputStr))));
+}
+
+
+// test
+function main(){
+ // bigint has suffix `n`
+ assert.strictEqual((<ASTNode>mainParse('123455667')).actualValue, 123455667n);
+ assert.strictEqual((<ASTNode>mainParse('000')).actualValue, 0n);
+ assert.strictEqual((<ASTNode>mainParse('1.22')).actualValue, 1.22);
+ assert.strictEqual((<ASTNode>mainParse('0.0')).actualValue, 0.0);
+ assert.strictEqual((<ASTNode>mainParse(`""`)).actualValue, "");
+ assert.strictEqual((<ASTNode>mainParse(`"the little town"`)).actualValue, `the little town`);
+ assert.strictEqual((<ASTNode>mainParse(`"\\\"Alice\\\""`)).actualValue, `"Alice"`);
+
+ assert.strictEqual((<ASTNode>mainParse(`foo`)).actualValue, "foo");
+ assert.strictEqual(astToSExp(mainParse(`let x = 12 in 23`)), "(let (x 12) 23)");
+ assert.strictEqual(astToSExp(mainParse(`let y = 10 in let x = 12 in 23`)), "(let (y 10) (let (x 12) 23))");
+ assert.strictEqual(astToSExp(mainParse(`let y = 10 in y := 12 in 23`)), "(let (y 10) (:= (y 12) 23))");
+ assert.strictEqual(astToSExp(mainParse(`fn x y -> 234`)), "(fn (x y) 234)");
+ assert.strictEqual(astToSExp(mainParse(`(add 12 23 )`)), "(add (12 23))");
+ assert.strictEqual(astToSExp(mainParse(`(foo x y)`)), "(foo (x y))");
+ assert.strictEqual(astToSExp(mainParse(`((foo 6 7) bar)`)), "((foo (6 7)) (bar))");
+ assert.strictEqual(astToSExp(mainParse(`fn x y ->
+ /* foo bar */
+ (foo x y)`)), "(fn (x y) (foo (x y)))");
+
+
+};
+
+main();
\ No newline at end of file
--- /dev/null
+//# sourceMappingURL=parser.js.map
\ No newline at end of file
--- /dev/null
+{"version":3,"file":"parser.js","sourceRoot":"","sources":["parser.ts"],"names":[],"mappings":""}
\ No newline at end of file
--- /dev/null
+{
+ "compilerOptions": {
+ "lib": ["es2020", "dom"],
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "target": "es2020",
+
+ "declaration": true,
+ "sourceMap": true,
+
+ "noEmitOnError": true,
+ "noUnusedLocals": true,
+ "strictNullChecks": true,
+ },
+ "exclude": ["node_modules"]
+}
--- /dev/null
+{
+ "defaultSeverity": "error",
+ "extends": [
+ "tslint:recommended"
+ ],
+ "jsRules": {},
+ "rules": {
+ "no-console": false
+ },
+ "rulesDirectory": []
+}
\ No newline at end of file
--- /dev/null
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/code-frame@^7.0.0":
+ version "7.23.5"
+ resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz"
+ integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==
+ dependencies:
+ "@babel/highlight" "^7.23.4"
+ chalk "^2.4.2"
+
+"@babel/helper-validator-identifier@^7.22.20":
+ version "7.22.20"
+ resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz"
+ integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
+
+"@babel/highlight@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz"
+ integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.22.20"
+ chalk "^2.4.2"
+ js-tokens "^4.0.0"
+
+"@eslint-community/eslint-utils@^4.4.0":
+ version "4.4.0"
+ resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz"
+ integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
+ dependencies:
+ eslint-visitor-keys "^3.3.0"
+
+"@eslint-community/regexpp@^4.5.1":
+ version "4.10.0"
+ resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz"
+ integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3":
+ version "1.2.8"
+ resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@types/json-schema@^7.0.12":
+ version "7.0.15"
+ resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz"
+ integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
+
+"@types/node@^20.10.4":
+ version "20.10.4"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.4.tgz#b246fd84d55d5b1b71bf51f964bd514409347198"
+ integrity sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==
+ dependencies:
+ undici-types "~5.26.4"
+
+"@types/semver@^7.5.0":
+ version "7.5.6"
+ resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz"
+ integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==
+
+"@typescript-eslint/eslint-plugin@^6.13.2":
+ version "6.13.2"
+ resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz"
+ integrity sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==
+ dependencies:
+ "@eslint-community/regexpp" "^4.5.1"
+ "@typescript-eslint/scope-manager" "6.13.2"
+ "@typescript-eslint/type-utils" "6.13.2"
+ "@typescript-eslint/utils" "6.13.2"
+ "@typescript-eslint/visitor-keys" "6.13.2"
+ debug "^4.3.4"
+ graphemer "^1.4.0"
+ ignore "^5.2.4"
+ natural-compare "^1.4.0"
+ semver "^7.5.4"
+ ts-api-utils "^1.0.1"
+
+"@typescript-eslint/parser@^6.13.2":
+ version "6.13.2"
+ resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz"
+ integrity sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==
+ dependencies:
+ "@typescript-eslint/scope-manager" "6.13.2"
+ "@typescript-eslint/types" "6.13.2"
+ "@typescript-eslint/typescript-estree" "6.13.2"
+ "@typescript-eslint/visitor-keys" "6.13.2"
+ debug "^4.3.4"
+
+"@typescript-eslint/scope-manager@6.13.2":
+ version "6.13.2"
+ resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz"
+ integrity sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==
+ dependencies:
+ "@typescript-eslint/types" "6.13.2"
+ "@typescript-eslint/visitor-keys" "6.13.2"
+
+"@typescript-eslint/type-utils@6.13.2":
+ version "6.13.2"
+ resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz"
+ integrity sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==
+ dependencies:
+ "@typescript-eslint/typescript-estree" "6.13.2"
+ "@typescript-eslint/utils" "6.13.2"
+ debug "^4.3.4"
+ ts-api-utils "^1.0.1"
+
+"@typescript-eslint/types@6.13.2":
+ version "6.13.2"
+ resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz"
+ integrity sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==
+
+"@typescript-eslint/typescript-estree@6.13.2":
+ version "6.13.2"
+ resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz"
+ integrity sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==
+ dependencies:
+ "@typescript-eslint/types" "6.13.2"
+ "@typescript-eslint/visitor-keys" "6.13.2"
+ debug "^4.3.4"
+ globby "^11.1.0"
+ is-glob "^4.0.3"
+ semver "^7.5.4"
+ ts-api-utils "^1.0.1"
+
+"@typescript-eslint/utils@6.13.2":
+ version "6.13.2"
+ resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz"
+ integrity sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.4.0"
+ "@types/json-schema" "^7.0.12"
+ "@types/semver" "^7.5.0"
+ "@typescript-eslint/scope-manager" "6.13.2"
+ "@typescript-eslint/types" "6.13.2"
+ "@typescript-eslint/typescript-estree" "6.13.2"
+ semver "^7.5.4"
+
+"@typescript-eslint/visitor-keys@6.13.2":
+ version "6.13.2"
+ resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz"
+ integrity sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==
+ dependencies:
+ "@typescript-eslint/types" "6.13.2"
+ eslint-visitor-keys "^3.4.1"
+
+ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ dependencies:
+ color-convert "^1.9.0"
+
+argparse@^1.0.7:
+ version "1.0.10"
+ resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz"
+ integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+ dependencies:
+ sprintf-js "~1.0.2"
+
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+braces@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+builtin-modules@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz"
+ integrity sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==
+
+chalk@^2.3.0, chalk@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+color-convert@^1.9.0:
+ version "1.9.3"
+ resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+ dependencies:
+ color-name "1.1.3"
+
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
+ integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
+
+commander@^2.12.1:
+ version "2.20.3"
+ resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+debug@^4.3.4:
+ version "4.3.4"
+ resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
+diff@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz"
+ integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
+
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
+escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
+ integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+
+eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1:
+ version "3.4.3"
+ resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
+ integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
+
+esprima@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz"
+ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+fast-glob@^3.2.9:
+ version "3.3.2"
+ resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz"
+ integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
+fastq@^1.6.0:
+ version "1.15.0"
+ resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz"
+ integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
+ dependencies:
+ reusify "^1.0.4"
+
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+function-bind@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
+ integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
+
+glob-parent@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob@^7.1.1:
+ version "7.2.3"
+ resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
+ integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.1.1"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+globby@^11.1.0:
+ version "11.1.0"
+ resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
+graphemer@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz"
+ integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
+
+has-flag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
+ integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
+
+hasown@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz"
+ integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==
+ dependencies:
+ function-bind "^1.1.2"
+
+ignore@^5.2.0, ignore@^5.2.4:
+ version "5.3.0"
+ resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz"
+ integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2:
+ version "2.0.4"
+ resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+is-core-module@^2.13.0:
+ version "2.13.1"
+ resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz"
+ integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
+ dependencies:
+ hasown "^2.0.0"
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-glob@^4.0.1, is-glob@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-yaml@^3.13.1:
+ version "3.14.1"
+ resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz"
+ integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
+merge2@^1.3.0, merge2@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+micromatch@^4.0.4:
+ version "4.0.5"
+ resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz"
+ integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+ dependencies:
+ braces "^3.0.2"
+ picomatch "^2.3.1"
+
+minimatch@^3.0.4, minimatch@^3.1.1:
+ version "3.1.2"
+ resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimist@^1.2.6:
+ version "1.2.8"
+ resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz"
+ integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+mkdirp@^0.5.3:
+ version "0.5.6"
+ resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz"
+ integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
+ dependencies:
+ minimist "^1.2.6"
+
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
+ integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+resolve@^1.3.2:
+ version "1.22.8"
+ resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz"
+ integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
+ dependencies:
+ is-core-module "^2.13.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+semver@^5.3.0:
+ version "5.7.2"
+ resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz"
+ integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
+
+semver@^7.5.4:
+ version "7.5.4"
+ resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
+ integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
+ dependencies:
+ lru-cache "^6.0.0"
+
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+sprintf-js@~1.0.2:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
+ integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==
+
+supports-color@^5.3.0:
+ version "5.5.0"
+ resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+ dependencies:
+ has-flag "^3.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+ts-api-utils@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz"
+ integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==
+
+tslib@^1.13.0, tslib@^1.8.1:
+ version "1.14.1"
+ resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
+ integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+
+tslint@^6.1.3:
+ version "6.1.3"
+ resolved "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz"
+ integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ builtin-modules "^1.1.1"
+ chalk "^2.3.0"
+ commander "^2.12.1"
+ diff "^4.0.1"
+ glob "^7.1.1"
+ js-yaml "^3.13.1"
+ minimatch "^3.0.4"
+ mkdirp "^0.5.3"
+ resolve "^1.3.2"
+ semver "^5.3.0"
+ tslib "^1.13.0"
+ tsutils "^2.29.0"
+
+tsutils@^2.29.0:
+ version "2.29.0"
+ resolved "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz"
+ integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
+ dependencies:
+ tslib "^1.8.1"
+
+typescript-parsec@^0.3.4:
+ version "0.3.4"
+ resolved "https://registry.npmjs.org/typescript-parsec/-/typescript-parsec-0.3.4.tgz"
+ integrity sha512-6RD4xOxp26BTZLopNbqT2iErqNhQZZWb5m5F07/UwGhldGvOAKOl41pZ3fxsFp04bNL+PbgMjNfb6IvJAC/uYQ==
+
+undici-types@~5.26.4:
+ version "5.26.5"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
+ integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==