From: Tan Kian-ting Date: Sun, 10 Dec 2023 15:25:18 +0000 (+0800) Subject: add some parsing w/o maintext X-Git-Url: https://git.kianting.info/?a=commitdiff_plain;h=829ac29ac3b64e9228416959a843faaff8c02fe1;p=anotherTypesetter add some parsing w/o maintext --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2f3d0d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +docs/.*#* +src/ch1/package-lock.json +src/ch1/node_modules \ No newline at end of file diff --git a/docs/defineASTandGrammar.md b/docs/defineASTandGrammar.md index 78c9990..a641bc9 100644 --- a/docs/defineASTandGrammar.md +++ b/docs/defineASTandGrammar.md @@ -61,25 +61,36 @@ C語言、Python語言就算有許多的關鍵字、操作符、符號或是常 所以我們可以定義以下的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])+ @@ -90,7 +101,14 @@ Float ::= [0-9]+ "." [0-9]+ 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來幫我們代勞。 」)。講一個簡單的案例吧: @@ -109,7 +127,7 @@ else{ } ``` -假設我們要將字串`s`的前3個字的match 0~9呢?如果會高階函數的話,引入一個`then`函數,然後把`match0to9`傳進去,這樣寫起來比較簡潔,行數可以比較少: +假設我們要將字串`s`的前3個字的match 0~9呢?如果會高階函數的話,引入一個`then`函數,然後把`match0to9`傳進去,這樣寫起來比較不會太糾結,比較好維護: ``` function thenDo(input, fun){ @@ -140,96 +158,143 @@ thenDo(thenDo(thenDo(sWrapped, match0to9), match0to9), match0to9) 安裝`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{ + // 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): ASTNode { + // extend value to ASTNode + const newNode : ASTNode = { + actualValue : BigInt(value.text) , + ...value}; + return newNode; } +function applyFloat(value: parsec.Token): ASTNode { + // extend value to ASTNode + const newNode : ASTNode = { + actualValue : parseFloat(value.text) , + ...value}; + return newNode; +} +function applyString(value: parsec.Token): 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(); +/* +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; ``` + ## 平面操作 ### 基本函數與直譯器 diff --git a/src/ch1/package.json b/src/ch1/package.json new file mode 100644 index 0000000..eec0cf8 --- /dev/null +++ b/src/ch1/package.json @@ -0,0 +1,24 @@ +{ + "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" + } +} diff --git a/src/ch1/src/index.d.ts b/src/ch1/src/index.d.ts new file mode 100644 index 0000000..95ee14b --- /dev/null +++ b/src/ch1/src/index.d.ts @@ -0,0 +1,27 @@ +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 { + actualValue?: bigint | number | string; +} +/** AST Tree */ +declare type AST = AST[] | ASTNode; +/** from AST to S-exp */ +export declare function astToSExp(ast: AST): any; +export {}; diff --git a/src/ch1/src/index.js b/src/ch1/src/index.js new file mode 100644 index 0000000..a710000 --- /dev/null +++ b/src/ch1/src/index.js @@ -0,0 +1,194 @@ +"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 diff --git a/src/ch1/src/index.js.map b/src/ch1/src/index.js.map new file mode 100644 index 0000000..2dfcf61 --- /dev/null +++ b/src/ch1/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/ch1/src/index.ts b/src/ch1/src/index.ts new file mode 100644 index 0000000..bbabf63 --- /dev/null +++ b/src/ch1/src/index.ts @@ -0,0 +1,360 @@ +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{ + // 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): ASTNode { + // extend value to ASTNode + const newNode : ASTNode = { + actualValue : BigInt(value.text) , + ...value}; + return newNode; +} + +function applyFloat(value: parsec.Token): ASTNode { + const newNode : ASTNode = { + actualValue : parseFloat(value.text) , + ...value}; + return newNode; +} + +function applyString(value: parsec.Token): 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): ASTNode { + const newNode : ASTNode = { + actualValue : value.text, + ...value}; + return newNode; +} + +/** apply LETTING. + * returns [let, [var, x], expr] */ +function applyLetting(input: [parsec.Token, // let + parsec.Token | undefined, // space + ASTNode, // var + parsec.Token| undefined, // space + parsec.Token, // = + parsec.Token| undefined, // space + AST, // val + parsec.Token| undefined, // space + parsec.Token, // in + parsec.Token| 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| undefined, // space + parsec.Token, // := + parsec.Token| undefined, // space + AST, // val + parsec.Token| undefined, // space + parsec.Token, // in + parsec.Token| 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| undefined, // space + parsec.Token, // -> + parsec.Token| 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 |undefined, // space + ASTNode, // head of callee + AST[] // tail of callee + ]){ + 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 : string){ + 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(); \ No newline at end of file diff --git a/src/ch1/src/test/parser.d.ts b/src/ch1/src/test/parser.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/ch1/src/test/parser.js b/src/ch1/src/test/parser.js new file mode 100644 index 0000000..7a6700d --- /dev/null +++ b/src/ch1/src/test/parser.js @@ -0,0 +1 @@ +//# sourceMappingURL=parser.js.map \ No newline at end of file diff --git a/src/ch1/src/test/parser.js.map b/src/ch1/src/test/parser.js.map new file mode 100644 index 0000000..c75b197 --- /dev/null +++ b/src/ch1/src/test/parser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"parser.js","sourceRoot":"","sources":["parser.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/src/ch1/src/test/parser.ts b/src/ch1/src/test/parser.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/ch1/tsconfig.json b/src/ch1/tsconfig.json new file mode 100644 index 0000000..069fa4a --- /dev/null +++ b/src/ch1/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "lib": ["es2020", "dom"], + "module": "commonjs", + "moduleResolution": "node", + "target": "es2020", + + "declaration": true, + "sourceMap": true, + + "noEmitOnError": true, + "noUnusedLocals": true, + "strictNullChecks": true, + }, + "exclude": ["node_modules"] +} diff --git a/src/ch1/tslint.json b/src/ch1/tslint.json new file mode 100644 index 0000000..0a27bf7 --- /dev/null +++ b/src/ch1/tslint.json @@ -0,0 +1,11 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "no-console": false + }, + "rulesDirectory": [] +} \ No newline at end of file diff --git a/src/ch1/yarn.lock b/src/ch1/yarn.lock new file mode 100644 index 0000000..587f778 --- /dev/null +++ b/src/ch1/yarn.lock @@ -0,0 +1,606 @@ +# 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==