Suivant le long de la lignes de la Façon d'représentent clairement une.b[c.d][e].f[g[h[j'.j]]] comme un objet de l'arbre?, comment voulez-vous écrire un algorithme permettant de générer que JS AST à partir de l'expression a.b[c.d][e].f[g[h[i.j]]]
? Je suis en train d'écrire un analyseur de générer une sorte de structure de l'objet à partir de cette expression (idéalement plus intuitive que la JS AST MemberExpression
l'un, d'où cette autre question). Je voudrais voir comment fonctionne l'algorithme pour construire le JavaScript MemberExpression
d'arbre en arbre.
Actuellement, j'ai cette sorte d'algorithme pour générer une sorte d' arbre (mais il semble être incorrect actuellement):
const patterns = [
[/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*/, 'name'],
[/^\[/, 'open'],
[/^\]/, 'close'],
[/^\./, 'stem']
]
console.log(parsePath('a.b[c.d][e].f[g[h[i.j]]]'))
function parsePath(str) {
let node
let nest = []
let result = nest
let stack = [nest]
while (str.length) {
nest = stack[stack.length - 1]
p:
for (let pattern of patterns) {
let match = str.match(pattern[0])
if (match) {
if (pattern[1] === 'name') {
node = {
form: `term`,
name: match[0],
link: []
}
nest.push(node)
} else if (pattern[1] === 'stem') {
stack.push(node.link)
} else if (pattern[1] === 'open') {
node = {
form: 'read',
link: []
}
nest.push(node)
stack.push(node.link)
} else if (pattern[1] === 'close') {
stack.pop()
}
str = str.substr(match[0].length)
break p
}
}
}
return result[0]
}
Le résultat souhaité est-ce (ou mieux, plus intuitive de la structure de données si vous êtes enclin à en créer un):
{
"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
}
La raison pour laquelle je me bats (partiellement) c'est que je n'aime pas ce MemberExpression
structure de l'arbre, il en arrière de sentiment et pas très intuitive. Donc si vous pouviez construire un système plus simple, plus simple structure de données qui serait l'idéal (c'est l'autre question), mais si non, alors un algorithme pour construire ce serait me faire aller.
Personnellement, je serais plutôt d'essayer de générer cette structure, comme je le trouve plus intuitif:
{
type: 'site',
site: [
{
type: 'term',
term: 'a'
},
{
type: 'term',
term: 'b'
},
{
type: 'sink',
sink: [
{
type: 'term',
term: 'c'
},
{
type: 'term',
term: 'd'
}
]
},
{
type: 'sink',
sink: [
{
type: 'term',
term: 'e'
}
]
},
{
type: 'term',
term: 'f'
},
{
type: 'sink',
sink: [
{
type: 'term',
term: 'g'
},
{
type: 'sink',
sink: [
{
type: 'term',
term: 'h'
},
{
type: 'sink',
sink: [
{
type: 'term',
term: 'i'
},
{
type: 'term',
term: 'j'
}
]
}
]
}
]
}
]
}
Mais soit on travaille pour moi (ou les deux).
Si nous passons à la deuxième, mon prochain problème sera de savoir comment convertir les données dans la structure du MemberExpression
arbre/structure de données :) Mais je vais essayer de le faire moi-même en premier. Donc, il est probablement préférable de construire les MemberExpression dans cette question, alors je peux travailler ça.