README
nv-js-parse
- nv-js-parse
- wrap of @babel/parser
- add some display/show/path/traverse methods , make it easy for manual-edit ast
install
- npm install nv-js-parse
usage
basic
const {tree,parse,unparse} = require('nv-js-parse')
var code = `class T {
#a = 1999
get() {
return this.#a
}
}`
> var t = tree(code)
> t
[program <Program> {"sourceType":"module","interpreter":null}] {}
astml is a simple syntax for manually writing ast
shape: %key %type:String %attr:Object %NL %listKey[%index:Int] %type:String %attr:Object %NL
%type must be ast-node-type of estree/ts/flow/jsx %key AND %listKey must be visitor/list-visitor of %type
> t.show_astml()
program <Program> {"sourceType":"module","interpreter":null}
body[0] <ClassDeclaration> {}
id <Identifier> {"name":"T"}
body <ClassBody> {}
body[0] <ClassPrivateProperty> {"static":false}
key <PrivateName> {}
id <Identifier> {"name":"a"}
value <NumericLiteral> {"value":1999}
body[1] <ClassMethod> {"generator":false,"async":false,"static":false,"computed":false,"kind":"method"}
key <Identifier> {"name":"get"}
body <BlockStatement> {}
body[0] <ReturnStatement> {}
argument <MemberExpression> {"computed":false}
object <ThisExpression> {}
property <PrivateName> {}
id <Identifier> {"name":"a"}
> t.show_code()
class T {
#a = 1999;
get() {
return this.#a;
}
}
> t.get_all_ast_bracket_paths()
[
'',
'["body"]["0"]',
'["body"]["0"]["id"]',
'["body"]["0"]["body"]',
'["body"]["0"]["body"]["body"]["0"]',
'["body"]["0"]["body"]["body"]["0"]["key"]',
'["body"]["0"]["body"]["body"]["0"]["key"]["id"]',
'["body"]["0"]["body"]["body"]["0"]["value"]',
'["body"]["0"]["body"]["body"]["1"]',
'["body"]["0"]["body"]["body"]["1"]["key"]',
'["body"]["0"]["body"]["body"]["1"]["body"]',
'["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]',
'["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]["argument"]',
'["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]["argument"]["object"]',
'["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]["argument"]["property"]',
'["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]["argument"]["property"]["id"]'
]
> t.ast["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]["argument"]["property"]["id"]
Node {
type: 'Identifier',
start: 67,
end: 68,
loc: SourceLocation {
start: Position { line: 4, column: 23 },
end: Position { line: 4, column: 24 },
filename: undefined,
identifierName: 'a'
},
name: 'a'
}
const2let
for debug using
actually ,const is a runtime-check feature
/* > function tst() { ... const a; const a; ^ Uncaught SyntaxError: Missing initializer in const declaration > a=100 100 > } } ^ */ cd =`function tst() { const a; a=100 }` > cd =`function tst() { const a; a=100 }` 'function tst() {\n const a;\n a=100\n}' > > const2let(cd) 'function tst() {\n let a;\n a = 100;\n}' >
hoist_func_decl
stage0, func declaration hoist
not the final ,only hoist to first ance-block, not to function block
var cd =`function A () { let x = 0 console.log(tst()) { console.log(tst()) function tst() {return(x+1)} } function tst() {return(x)} }` s0 = split_var_decl(cd) s1 = split_var_declor(s0) s2 = hoist_var(s1) s3 = hoist_func_decl(s2) > console.log(s3) function A() { function tst() { return x; } let x; x = 0; console.log(tst()); { function tst() { return x + 1; } console.log(tst()); } }
fdecl2fexpr
must be used after hoist_func_decl
var cd = ` function tst(u,v) { let a=100; function inner() { var x; function tst() {} } } ` > console.log(fdecl2fexpr(cd)) var tst = function tst(u, v) { let a = 100; var inner = function inner() { var x; var tst = function tst() {}; }; };
cdecl2cexpr
class declaration to class expression
var cd = ` class A { method() { class B {} class C {} function tst() { class D {} } } } ` > console.log(cdecl2cexpr(cd)) let A = class A { method() { let B = class B {}; let C = class C {}; function tst() { let D = class D {}; } } };
split_var_decl
- for debug AND hoist using
const {split_var_decl} = require("nv-js-parse")
var code = `
function tst() {
let a,b=3,c;
return(a+b+c)
}`
> console.log(split_var_decl(code))
function tst() {
let a;
let b = 3;
let c;
return a + b + c;
}
var code = `
function tst() {
let x,[{a,b},c]=[{a:666,b:777},3],y;
return(a+b+c)
}`
> console.log(split_var_decl(code))
function tst() {
let x;
let [{
a,
b
}, c] = [{
a: 666,
b: 777
}, 3];
let y;
return a + b + c;
}
> tst()
1446
>
> var cd = `function tst() {
... var a,b=8;
... for(let i=0,j;i<3;i++,j++) {let {x,y}={}}
... var c = a+b
... }`
> console.log(split_var_decl(cd))
function tst() {
var a;
var b = 8;
{ //----------------
let i = 0;
let j;
for (; i < 3; i++, j++) {
let {
x,
y
} = {};
}
} //------------------special handle of for AND forin AND forof
var c = a + b;
}
split_var_declor
- for debug AND hoist using
- must be used after split_var_decl
var cd = `
function tst(u,v) {
let x,e,ee;
let [{a,b=e='EEEEE',...f},c=333,d,...g]=[{a:666,b:777},3];
let [{aa,bb=ee='1111111',...ff},cc=333,dd,...gg]=[{aa:666,bb:777},3];
let [] = [],[,] =[],[...args] = [1,2],{...D} = {1:2,3:4},[A] = [1,2],{B} = {B:2,3:4},[C=10] = [],{E=999} = {};
return([u,v,x,a,b,e,f,c,d,g,aa,bb,ee,ff,cc,dd,gg,args,D,A,B,C,E])
}
`
/*
> eval(`(${cd})(100,500)`)
[
100, 500,
undefined, 666,
777, undefined,
{}, 3,
undefined, [],
666, 777,
undefined, {},
3, undefined,
[], [ 1, 2 ],
{ '1': 2, '3': 4 }, 1,
2, 10,
999
]
>
*/
s0 = split_var_decl(cd)
console.log(s0)
/*
function tst(u, v) {
let x;
let e;
let ee;
let [{
a,
b = e = 'EEEEE',
...f
}, c = 333, d, ...g] = [{
a: 666,
b: 777
}, 3];
let [{
aa,
bb = ee = '1111111',
...ff
}, cc = 333, dd, ...gg] = [{
aa: 666,
bb: 777
}, 3];
let [] = [];
let [,] = [];
let [...args] = [1, 2];
let { ...D
} = {
1: 2,
3: 4
};
let [A] = [1, 2];
let {
B
} = {
B: 2,
3: 4
};
let [C = 10] = [];
let {
E = 999
} = {};
return [u, v, x, a, b, e, f, c, d, g, aa, bb, ee, ff, cc, dd, gg, args, D, A, B, C, E];
}
*/
/*
> eval(`(${s0})(100,500)`)
[
100, 500,
undefined, 666,
777, undefined,
{}, 3,
undefined, [],
666, 777,
undefined, {},
3, undefined,
[], [ 1, 2 ],
{ '1': 2, '3': 4 }, 1,
2, 10,
999
]
>
*/
s1 = split_var_declor(s0)
console.log(s1)
/*
function tst(u, v) {
let x;
let e;
let ee;
let a;
let b;
let f;
let c;
let d;
let g;
[{
a,
b = e = 'EEEEE',
...f
}, c = 333, d, ...g] = [{
a: 666,
b: 777
}, 3];
let aa;
let bb;
let ff;
let cc;
let dd;
let gg;
[{
aa,
bb = ee = '1111111',
...ff
}, cc = 333, dd, ...gg] = [{
aa: 666,
bb: 777
}, 3];
[] = [];
[,] = [];
let args;
[...args] = [1, 2];
let D;
({ ...D
} = {
1: 2,
3: 4
});
let A;
[A] = [1, 2];
let B;
({
B
} = {
B: 2,
3: 4
});
let C;
[C = 10] = [];
let E;
({
E = 999
} = {});
return [u, v, x, a, b, e, f, c, d, g, aa, bb, ee, ff, cc, dd, gg, args, D, A, B, C, E];
}
*/
/*
> eval(`(${s1})(100,500)`)
[
100, 500,
undefined, 666,
777, undefined,
{}, 3,
undefined, [],
666, 777,
undefined, {},
3, undefined,
[], [ 1, 2 ],
{ '1': 2, '3': 4 }, 1,
2, 10,
999
]
>
*/
var cd = `function tst() {for(let i=1,[x,y]=[888];i<3;i++) {}}`
s0 = split_var_decl(cd)
s1 = split_var_declor(s0)
console.log(s1)
/*
function tst() {
{
let i;
i = 1;
let x;
let y;
[x, y] = [888];
for (; i < 3; i++) {}
}
}
*/
var cd = `function tst() {for(let i;i<3;i++) {}}`
s0 = split_var_decl(cd)
s1 = split_var_declor(s0)
console.log(s1)
/*
function tst() {
{
let i;
for (; i < 3; i++) {}
}
}
*/
var cd = `
async function tst() {
let arr =[];
let d = {};
let g = (async function *(){})();
for(let i=1,y;i<3;i++) {}
for(let ele of arr) {}
for(let k in d) {}
for await (let each of g) {}
}
`
s0 = split_var_decl(cd)
s1 = split_var_declor(s0)
console.log(s1)
/*
async function tst() {
let arr;
arr = [];
let d;
d = {};
let g;
g = async function* () {}();
{
let i;
i = 1;
let y;
for (; i < 3; i++) {}
}
{
let ele;
for (ele of arr) {}
}
{
let k;
for (k in d) {}
}
{
let each;
for await (each of g) {}
}
}
*/
hoist_var
must be used after split_var_decl -> split_var_declor
const { split_var_decl, split_var_declor, tree, hoist_var, } = require("nv-js-parse") var cd = ` function tst(u,v) { let x; { var y=888; { var [z,{w,r}] = [1,{w:2,r:3}]; let A; } } } ` s0 = split_var_decl(cd) s1 = split_var_declor(s0) s2 = hoist_var(s1) > console.log(s2) function tst(u, v) { let x; var y; var z; var w; var r; { y = 888; { [z, { w, r }] = [1, { w: 2, r: 3 }]; let A; } } }
rare special cases
> var cd =`
... function tst() {
... var a;
... {
..... var a;
..... a = 13;
..... }
... }`
>
> hoist_var(cd)
'function tst() {\n var a;\n var a;\n {\n a = 13;\n }\n}'
> console.log(hoist_var(cd))
function tst() {
var a;
var a;
{
a = 13;
}
}
var cd =`
var tst;
tst = function tst() {
var a;
{
var a;
}
};
`
> var cd =`
... var tst;
...
... tst = function tst() {
... var a;
... {
..... var a;
..... }
... };
... `
> console.log(hoist_var(cd))
var tst;
tst = function tst() {
var a;
var a;
{}
};
>
merge_dupe_var_decl
- must be used after hoist_var
var cd = `
function tst() {
var a;
var a;
{
a = 13;
}
}`
merge_dupe_var_decl(cd)
> console.log(merge_dupe_var_decl(cd))
[
[ id <Identifier> {"name":"tst"}] {},
[ id <Identifier> {"name":"a"}] {},
[ id <Identifier> {"name":"a"}] {},
[ left <Identifier> {"name":"a"}] {}
]
function tst() {
var a;
{
a = 13;
}
}
when conflict with params-
var cd= `function tst(a) {
var a;
return(a)
}`
> console.log(merge_dupe_var_decl(cd))
function tst(a) {
return a;
}
split_nonidlval_asgn_expr
- must be used after split_var_declor
- if the AssignmentExpression left(LVal) is NOT direct Identifier
- (such as MemberExpression,ArrayPattern,ObjectPattern....)
- it will split it to three part, see below
var cd =`[z,{w,r}] = [1,{w:2,r:3}]`
console.log(split_nonidlval_asgn_expr(cd))
/*
let ___swapper_b1cf8a9c_$AssignmentExpression___ = [1, {
w: 2,
r: 3
}];
[z, {
w,
r
}] = ___swapper_b1cf8a9c_$AssignmentExpression___;
___swapper_b1cf8a9c_$AssignmentExpression___ = undefined;
*/
var cd = `
function tst(u,v) {
let x;
{
var y=888;
{
var [z,{w,r}] = [1,{w:2,r:3}];
var [u,{v},...X] = [10,{v:20}];
let A;
var B=D=E=1111
}
}
var [z,{w,r}] = [10,{w:20,r:30}];
}
`
s0 = split_var_decl(cd)
s1 = split_var_declor(s0)
s2 = hoist_var(s1)
s3 = split_nonidlval_asgn_expr(s2)
s4 = merge_dupe_var_decl(s3)
console.log(s4)
/*
function tst(u, v) {
var y;
var z;
var w;
var r;
var X;
var B;
let x;
{
y = 888;
{
let ___swapper_ec071153_$AssignmentExpression___ = [1, {
w: 2,
r: 3
}];
[z, {
w,
r
}] = ___swapper_ec071153_$AssignmentExpression___;
___swapper_ec071153_$AssignmentExpression___ = undefined;
let ___swapper_fcc8fd5d_$AssignmentExpression___ = [10, {
v: 20
}];
[u, {
v
}, ...X] = ___swapper_fcc8fd5d_$AssignmentExpression___;
___swapper_fcc8fd5d_$AssignmentExpression___ = undefined;
let A;
B = D = E = 1111;
}
}
let ___swapper_b72b9d99_$AssignmentExpression___ = [10, {
w: 20,
r: 30
}];
[z, {
w,
r
}] = ___swapper_b72b9d99_$AssignmentExpression___;
___swapper_b72b9d99_$AssignmentExpression___ = undefined;
}
*/
var_to_let
must be used after merge_dupe_var_decl
var cd = ` function tst() { var a; var a; { a = 13; } }` var s0 = merge_dupe_var_decl(cd) var s1 = var2let(s0) > console.log(s1) function tst() { let a; { a = 13; } }
ternery to if-else
const conexpr_to_ifelse = require("nv-js-parse");
var cd0 = `function tst(a,b,c,d,e) {return(a?b:c?d:e)}`;
/*
> function tst(a,b,c,d,e) {return(a?b:c?d:e)}
> tst(true,false,true,'d','e')
false
>
*/
console.log(conexpr_to_ifelse(cd0));
/*
function tst(a, b, c, d, e) {
return (() => {
if (a) {
return b;
} else {
return (() => {
if (c) {
return d;
} else {
return e;
}
})();
}
})();
}
> tst(true,false,true,'d','e')
false
>
*/
var cd1 = `function tst(a,b,c,d,e) {return((a?b:c)?d:e)}`;
/*
function tst(a,b,c,d,e) {return((a?b:c)?d:e)}
> tst(true,false,true,'d','e')
'e'
>
*/
console.log(conexpr_to_ifelse(cd1));
/*
function tst(a, b, c, d, e) {
return (() => {
if ((() => {
if (a) {
return b;
} else {
return c;
}
})()) {
return d;
} else {
return e;
}
})();
}
> tst(true,false,true,'d','e')
'e'
>
*/
var cd2 = `
function tst(a,b,c,d,e) {
let x = a?b:null
function inner() {
let y = a?(
c?d:e
):(
d?100:(e?200:300)
)
}
return(inner())
}
`
console.log(conexpr_to_ifelse(cd2));
/*
function tst(a, b, c, d, e) {
let x = (() => {
if (a) {
return b;
} else {
return null;
}
})();
function inner() {
let y = (() => {
if (a) {
return (() => {
if (c) {
return d;
} else {
return e;
}
})();
} else {
return (() => {
if (d) {
return 100;
} else {
return (() => {
if (e) {
return 200;
} else {
return 300;
}
})();
}
})();
}
})();
}
return inner();
}
*/
tree
- read-only
const {tree} = require("nv-js-parse");
var cd2 =`
function outter() {
let a ;
function inner() {
b
a;
{
a;
}
}
}
`
var t = tree(cd2,false/*delete loc info*/);
var arr = t.$sdfs()
var ids = arr.filter(r=>r.path.node.type==='Identifier')
> ids.map(r=>r.path.node.name)
[ 'outter', 'a', 'inner', 'b', 'a', 'a' ]
>
> ids[0].get_closure_scope_nd()
[Program] {}
>
> ids[1].get_closure_scope_nd().show_code()
> ids[1].get_ast().name
'a'
> ids[1].get_closure_scope_nd().show_code()
function outter() {
let a;
function inner() {
b;
a;
{
a;
}
}
}
> ids[2].get_ast().name
'inner'
> ids[2].get_closure_scope_nd().show_code()
function outter() {
let a;
function inner() {
b;
a;
{
a;
}
}
}
> ids[3].get_ast().name
'b'
> var top = ids[3].get_closure_scope_nd()
[Program] {}
>
> top.path.scope.globals
[Object: null prototype] {
b: Node {
type: 'Identifier',
start: 80,
end: 81,
loc: SourceLocation {
start: [Position],
end: [Position],
filename: undefined,
identifierName: 'b'
},
name: 'b'
}
}
>
> ids[5].get_ast().name
'a'
>
> ids[5].get_closure_scope_nd().show_code()
function outter() {
let a;
function inner() {
b;
a;
{
a;
}
}
}
var cd3 = `
function tst(A,B) {
function inner() {
return(A)
}
}
`
var t = tree(cd3);
var arr = t.$sdfs()
var ids = arr.filter(r=>r.path.node.type==='Identifier')
ids.map(r=>r.path.node.name)
[ 'tst', 'A', 'B', 'inner', 'A' ]
> ids[1].get_closure_scope_nd().show_code()
function tst(A, B) {
function inner() {
return A;
}
}
undefined
> ids[1].get_ast().name
'A'
> ids[1].get_closure_scope_nd().show_code()
function tst(A, B) {
function inner() {
return A;
}
}
> ids[4].get_ast().name
'A'
> ids[4].get_closure_scope_nd().show_code()
function tst(A, B) {
function inner() {
return A;
}
}
binding
var t = tree(`
let P;
function X([tst=666,{a,b}]){
let uuu=y;
class C {}
}
try{}catch({e}) { let vvv;}
var D = { s(u,{v}){} }
class U {}
{let m;}
for(let j=0;j<5;j++) {}
for(let k in X) {}
for(let ele of X) {}
`)
t.get_decl_ids().map(r=>r.get_sig_plstr())
/*
[
'body-declarations-id',
'body-id',
'params-elements-left',
'params-elements-properties-key',
'params-elements-properties-key',
'body-body-declarations-id',
'body-body-id',
'param-properties-key',
'body-body-declarations-id',
'body-declarations-id',
'params',
'params-properties-key',
'body-id',
'body-declarations-id',
'init-declarations-id',
'left-declarations-id',
'left-declarations-id'
]
*/
var fdecl = t.FunctionDeclaration()[0];
/*
> fdecl.show_code()
function X([tst = 666, {
a,
b
}]) {
let uuu = y;
class C {}
}
*/
> fdecl.get_binding_def_ids()
{
var: [],
let: [
[ id <Identifier> {"name":"uuu"}] {}
],
const: [],
fdecl: [],
cdecl: [
[ id <Identifier> {"name":"C"}] {}
],
params: [
[ left <Identifier> {"name":"tst"}] {},
[ value <Identifier> {"name":"a"}] {},
[ value <Identifier> {"name":"b"}] {}
],
global: [],
catch_param: []
}
>
var cd = `
function tst() {
let [{
a,
b = e = 'EEEEE',
...f
},
c = 333, d,
[A,B,C,{E,F}],
...g
] =[];
}
`
var t = tree(cd);
var fdecl = t.$sdfs()[1]
> fdecl.get_decl_ids().map(r=>r.ast.name)
[
'a', 'b', 'f', 'c',
'd', 'A', 'B', 'C',
'E', 'F', 'g'
]
>
function tst() {
let [{
a,
b = e = 'EEEEE', //identifier-e ast-path-sign not match
...f
},
c = 333, d,
[A,B,C,{E,F}],
...g
] =[{},undefined,undefined,[1,2,3,{}]];
}
/*
> tst()
> e
'EEEEE' //e is global
*/
decl id type
for static trace using
var cd = ` function tst(a,{b}) { let c; { var d; } try{}catch(e){} } let _f1 = function (f) {} const _lambda = (g)=> {} class C { method(h,[j]) {} #method([k,{l}]){} } let O = {m(n){}} try{}catch({p}){} for(let i=0;i<5;i++) {} for(let {I}={I:0};i<5;i++) {} for(let ele of []) {} for(let [ELE] of [[1],[2]]) {} for(let k in {}) {} for(let {length} in [0,1,2,3,4,5,6,7,8,9,10]) {} //this is a valid syntax ` var t = tree(cd) > ids = t.get_decl_ids() [ [ id <Identifier> {"name":"tst"}] {}, [ params[0] <Identifier> {"name":"a"}] {}, [ value <Identifier> {"name":"b"}] {}, [ id <Identifier> {"name":"c"}] {}, [ id <Identifier> {"name":"d"}] {}, [ param <Identifier> {"name":"e"}] {}, [ id <Identifier> {"name":"_f1"}] {}, [ params[0] <Identifier> {"name":"f"}] {}, [ id <Identifier> {"name":"_lambda"}] {}, [ params[0] <Identifier> {"name":"g"}] {}, [ id <Identifier> {"name":"C"}] {}, [ params[0] <Identifier> {"name":"h"}] {}, [ elements[0] <Identifier> {"name":"j"}] {}, [ elements[0] <Identifier> {"name":"k"}] {}, [ value <Identifier> {"name":"l"}] {}, [ id <Identifier> {"name":"O"}] {}, [ params[0] <Identifier> {"name":"n"}] {}, [ value <Identifier> {"name":"p"}] {}, [ id <Identifier> {"name":"i"}] {}, [ value <Identifier> {"name":"I"}] {}, [ id <Identifier> {"name":"ele"}] {}, [ elements[0] <Identifier> {"name":"ELE"}] {}, [ id <Identifier> {"name":"k"}] {}, [ value <Identifier> {"name":"length"}] {} ] > > ids[0].is_fdecl_id() true > ids[1].is_fdecl_param_id() true > ids[2].is_fdecl_param_id() true > > ids[3].is_let_decl_id() true > > ids[4].is_var_decl_id() true > > ids[5].is_catch_param_id() true > > ids[6].is_let_decl_id() true > > ids[7].is_fexpr_param_id() true > > ids[8].is_const_decl_id() true > > ids[9].is_arrow_param_id() true > > ids[10].is_cdecl_id() true > > ids[11].is_cls_method_param_id() true > > ids[12].is_cls_method_param_id() true > > ids[13].is_cls_priv_method_param_id() true > > ids[14].is_cls_priv_method_param_id() true > > ids[15].is_let_decl_id() true > > ids[16].is_obj_method_param_id() true > > ids[17].is_catch_param_id() true > > ids[18].is_for_init_id() true > > ids[19].is_for_init_id() true > > ids[20].is_forof_id() true > ids[21].is_forof_id() true > ids[22].is_forin_id() true > ids[23].is_forin_id() true >
find escaped id
var cd = `
function tst(a) {
let b=10,c={'key':X};
a = b+c ;
{
let u = 5;
a = a + u;
}
return(a)
}
`
var t = tree(cd)
var f = t.$fstch()
> f.get_decl_ids()
[
[ params[0] <Identifier> {"name":"a"}] {},
[ id <Identifier> {"name":"b"}] {},
[ id <Identifier> {"name":"c"}] {},
[ id <Identifier> {"name":"u"}] {} //后代block内的
]
>
> f.get_own_local_decl_ids()
{
var: [],
let: [
[ id <Identifier> {"name":"b"}] {},
[ id <Identifier> {"name":"c"}] {}
],
const: [],
fdecl: [],
cdecl: [],
params: [
[ params[0] <Identifier> {"name":"a"}] {}
],
global: [],
catch_param: []
}
>
> f.get_own_local_escaped_decl_ids()
[
[ params[0] <Identifier> {"name":"a"}] {} // 参数 a 被里层 block 使用
]
>
> f.get_own_local_noescaped_decl_ids()
[
[ id <Identifier> {"name":"b"}] {},
[ id <Identifier> {"name":"c"}] {}
]
>
> f.get_nolocal_refed_ids()
[
[ value <Identifier> {"name":"X"}] {}
]
>
> f.get_nodecl_notation_ids()
[
[ value <Identifier> {"name":"X"}] {},
[ left <Identifier> {"name":"a"}] {},
[ left <Identifier> {"name":"b"}] {},
[ right <Identifier> {"name":"c"}] {},
[ left <Identifier> {"name":"a"}] {}, //<a> = a + u
[ left <Identifier> {"name":"a"}] {}, // a = <a> + u
[ right <Identifier> {"name":"u"}] {}, // a = a + <u>
[ argument <Identifier> {"name":"a"}] {}
]
>
> f.get_own_local_nodecl_ids()
[
[ left <Identifier> {"name":"a"}] {}, //<a>=b+c
[ left <Identifier> {"name":"b"}] {}, //a=<b>+c
[ right <Identifier> {"name":"c"}] {}, //a=b+<c>
[ argument <Identifier> {"name":"a"}] {} //return(<a>)
]
>
TAC format
used in a special js-runtime
normally useless
> const {tree} = require("nv-js-parse") > var src =`ReactDOM.render(<App />, document.getElementById('root'));` > var t = tree(src,"typescript",true/*enable_jsx*/) > t.$sdfs() [ [program <Program> {"sourceType":"module","interpreter":null}] {}, [ body[0] <ExpressionStatement> {}] {}, [ expression <CallExpression> {}] {}, [ callee <MemberExpression> {"computed":false}] {}, [ object <Identifier> {"name":"ReactDOM"}] {}, [ property <Identifier> {"name":"render"}] {}, [ arguments[0] <JSXElement> {}] {}, [ openingElement <JSXOpeningElement> {"selfClosing":true}] {}, [ name <JSXIdentifier> {"name":"App"}] {}, [ arguments[1] <CallExpression> {}] {}, [ callee <MemberExpression> {"computed":false}] {}, [ object <Identifier> {"name":"document"}] {}, [ property <Identifier> {"name":"getElementById"}] {}, [ arguments[0] <StringLiteral> {"value":"root"}] {} ] > // K = listKey:AstString | Key:AstString // T = K@TYPE // Attr = Object // Ele = [T,Attr?,Array<Ele>?] // > var tac = t.to_tac() > console.dir(tac,{depth:null}) [ 'program@Program',{ sourceType: 'module', interpreter: null }, [ 'body@ExpressionStatement', [ 'expression@CallExpression', [ 'callee@MemberExpression',{ computed: false },[ 'object@Identifier',{ name: 'ReactDOM' }, 'property@Identifier',{ name: 'render' } ], 'arguments@JSXElement',[ 'openingElement@JSXOpeningElement',{ selfClosing: true },[ 'name@JSXIdentifier', { name: 'App' } ] ], 'arguments@CallExpression',[ 'callee@MemberExpression',{ computed: false },[ 'object@Identifier',{ name: 'document' }, 'property@Identifier',{ name: 'getElementById' } ], 'arguments@StringLiteral',{ value: 'root' } ] ] ] ] ]
API
- parse(code)
- unparse(ast)
- const2let(code)
- hoist_func_decl(code)
- fdecl2fexpr(code)
- cdecl2cexpr(code)
- split_var_decl(code)
- split_var_declor(code)
- hoist_var(code)
- split_nonidlval_asgn_expr(code)
- merge_dupe_var_decl(code)
- var_to_let(code)
- tree(code)
LICENSE
- ISC