Niveau d'indentation de Parse avec PEG.js

J'ai essentiellement la même question que PEG pour l'indentation de style Python , mais j'aimerais obtenir un peu plus de direction concernant cette réponse .

La réponse génère avec succès un ensemble de chaînes qui sont chaque ligne d'entrée avec 'INDENT' et 'DEDENT' entre les lignes. Il semble qu'il soit assez utilisé PEG.js tokenize, mais aucune analyse réelle ne se produit.

Alors, comment puis-je étendre son exemple pour faire des analyses réelles?

À titre d'exemple, comment puis-je modifier cette grammaire:

start = obj obj = id:id children:(indent obj* outdent)? { var o = {}; o[id] = children[1]; return (children[1] ? o : id); } id = [az] indent = '{' outdent = '}' 

Utiliser l'indentation au lieu des accolades pour délimiter les blocs et obtenir toujours la même sortie?

(Utilisez http://pegjs.majda.cz/online pour tester cette grammaire avec la saisie suivante: a{bcd{zyx{}}} )

Parser:

 // do not use result cache, nor line and column tracking { var indentStack = [], indent = ""; } start = INDENT? l:line { return l; } line = SAMEDENT line:(!EOL c:. { return c; })+ EOL? children:( INDENT c:line* DEDENT { return c; })? { var o = {}; o[line] = children; return children ? o : line.join(""); } EOL = "\r\n" / "\n" / "\r" SAMEDENT = i:[ \t]* &{ return i.join("") === indent; } INDENT = &(i:[ \t]+ &{ return i.length > indent.length; } { indentStack.push(indent); indent = i.join(""); pos = offset; }) DEDENT = { indent = indentStack.pop(); } 

Contribution:

 a b c d z y x 

Sortie:

 { "a": [ "b", "c", { "d": [ "z", "y", "x" ] } ] } 

Il ne peut pas analyser un objet vide (dernier x ), mais il devrait être facile à résoudre. Trick ici est la règle SAMEDENT , elle réussit lorsque le niveau d'indentation n'a pas changé. DEDENT et DEDENT changent le niveau d'indentation actuel sans changer de position dans le texte pos = offset .