我已經找到了一種a.b[c.d][e].f[g[h[i.j]]]使用我自己的樹格式來表示運算式的方法。該運算式表示為一棵樹,如下所示:
{
"form": "nest",
"link": [
{
"form": "site",
"name": "a"
},
{
"form": "site",
"name": "b"
},
{
"form": "nest",
"link": [
{
"form": "site",
"name": "c"
},
{
"form": "site",
"name": "d"
}
]
},
{
"form": "nest",
"link": [
{
"form": "site",
"name": "e"
}
]
},
{
"form": "site",
"name": "f"
},
{
"form": "nest",
"link": [
{
"form": "site",
"name": "g"
},
{
"form": "nest",
"link": [
{
"form": "site",
"name": "h"
},
{
"form": "nest",
"link": [
{
"form": "site",
"name": "i"
},
{
"form": "site",
"name": "j"
}
]
}
]
}
]
}
]
}
現在,相同的字串運算式也由以下 JS AST 樹結構表示MemberExpression:
{
"type": "MemberExpression",
"object": {
"type": "MemberExpression",
"object": {
"type": "MemberExpression",
"object": {
"type": "MemberExpression",
"object": {
"type": "MemberExpression",
"object": {
"type": "Identifier",
"name": "a"
},
"property": {
"type": "Identifier",
"name": "b"
},
"computed": false
},
"property": {
"type": "MemberExpression",
"object": {
"type": "Identifier",
"name": "c"
},
"property": {
"type": "Identifier",
"name": "d"
},
"computed": false
},
"computed": true
},
"property": {
"type": "Identifier",
"name": "e"
},
"computed": true
},
"property": {
"type": "Identifier",
"name": "f"
},
"computed": false
},
"property": {
"type": "MemberExpression",
"object": {
"type": "Identifier",
"name": "g"
},
"property": {
"type": "MemberExpression",
"object": {
"type": "Identifier",
"name": "h"
},
"property": {
"type": "MemberExpression",
"object": {
"type": "Identifier",
"name": "i"
},
"property": {
"type": "Identifier",
"name": "j"
},
"computed": false
},
"computed": true
},
"computed": true
},
"computed": true
}
所以這兩個樹結構代表同一個字串運算式a.b[c.d][e].f[g[h[i.j]]]。您會注意到在第一個“巢”結構上,有兩種型別的物件,站點和巢。站點只是一個名稱,而嵌套在 JS AST 術語中表示“計算”屬性。所以一個巢就像parent[this_is_a_nest[and_another_nest]],而parent.site1.site2。
你如何將第一個樹結構轉換成第二個?
到目前為止我所擁有的并沒有真正到達那里,這很令人困惑。
console.log(JSON.stringify(transform(getNest()), null, 2))
function transform(nest) {
let i = 0
let stack = []
while (i < nest.link.length) {
let object = nest.link[i ]
let property = nest.link[i]
let member = {
type: 'MemberExpression'
}
stack.push(member)
if (object.form === 'nest') {
member.object = transform(object)
} else {
member.object = {
type: 'Identifier',
name: object.name
}
}
if (property) {
if (property.form === 'nest') {
member.property = transform(property)
member.computed = true
} else {
member.property = {
type: 'Identifier',
name: property.name
}
}
}
}
let object = stack.pop()
while (stack.length) {
let nextObject = stack.pop()
nextObject.object = object
object = nextObject
}
return object
}
function getNest() {
return {
"form": "nest",
"link": [
{
"form": "site",
"name": "a"
},
{
"form": "site",
"name": "b"
},
{
"form": "nest",
"link": [
{
"form": "site",
"name": "c"
},
{
"form": "site",
"name": "d"
}
]
},
{
"form": "nest",
"link": [
{
"form": "site",
"name": "e"
}
]
},
{
"form": "site",
"name": "f"
},
{
"form": "nest",
"link": [
{
"form": "site",
"name": "g"
},
{
"form": "nest",
"link": [
{
"form": "site",
"name": "h"
},
{
"form": "nest",
"link": [
{
"form": "site",
"name": "i"
},
{
"form": "site",
"name": "j"
}
]
}
]
}
]
}
]
}
}
還不知道如何以解決問題的方式簡化問題。
我不知道這是否有幫助(MemberExpression 的 acornjs 決議器)。
uj5u.com熱心網友回復:
這應該這樣做:
function transform(treeNode) {
if (treeNode.form == "site") {
return {
"type": "Identifier",
"name": treeNode.name,
};
} else if (treeNode.form == "nest") {
const [base, ...props] = treeNode.link;
console.assert(base.form == "site");
return props.reduce((lhs, rhs) => {
if (rhs.form == "nest") {
return {
"type": "MemberExpression",
"object": lhs,
"property": transform(rhs), // returns MemberExpression or (if singleton) Identifier
"computed": true,
};
} else if (rhs.form == "site") {
return {
"type": "MemberExpression",
"object": lhs,
"property": transform(rhs), // returns Identifier
"computed": false,
};
}
}, transform(base));
}
}
您當然可以將減速器簡化為
props.reduce((lhs, rhs) => ({
"type": "MemberExpression",
"object": lhs,
"property": transform(rhs),
"computed": rhs.form == "nest",
}), transform(base));
uj5u.com熱心網友回復:
在看到@Bergi 的回答之后,我剛剛解決了這個問題,太激動了!
function transform(nest) {
let i = 0
let stack = [{
type: 'Identifier',
name: nest.link[i ].name
}]
while (i < nest.link.length) {
const object = stack.shift()
const node = nest.link[i ]
if (node.form === 'nest') {
const property = transform(node)
stack.push({
object: object,
property,
computed: true
})
} else {
let property = {
type: 'Identifier',
name: node.name
}
stack.push({
object: object,
property: property,
computed: false
})
}
}
return stack.shift()
}
輸出是:
{
"object": {
"object": {
"object": {
"object": {
"object": {
"type": "Identifier",
"name": "a"
},
"property": {
"type": "Identifier",
"name": "b"
},
"computed": false
},
"property": {
"object": {
"type": "Identifier",
"name": "c"
},
"property": {
"type": "Identifier",
"name": "d"
},
"computed": false
},
"computed": true
},
"property": {
"type": "Identifier",
"name": "e"
},
"computed": true
},
"property": {
"type": "Identifier",
"name": "f"
},
"computed": false
},
"property": {
"object": {
"type": "Identifier",
"name": "g"
},
"property": {
"object": {
"type": "Identifier",
"name": "h"
},
"property": {
"object": {
"type": "Identifier",
"name": "i"
},
"property": {
"type": "Identifier",
"name": "j"
},
"computed": false
},
"computed": true
},
"computed": true
},
"computed": true
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/363939.html
標籤:javascript 算法 树 抽象语法树
