2012-07-25 26 views
9

Mam zasadniczo to samo pytanie jak PEG for Python style indentation, ale chciałbym trochę więcej kierunek dotyczących this answer.Parse poziom wcięcia z PEG.js

Odpowiedź powodzeniem generuje tablicę łańcuchów, które każdy wiersz wejścia z „” i „TIRET DEDENT” między wierszami. Wygląda na to, że jest dość często używany w PEG.js do tokenizacji, ale nie ma prawdziwego przetwarzania.

Więc jak mogę przedłużyć jego przykład zrobić jakąś rzeczywistą analizowania?

Jako przykład, w jaki sposób mogę zmienić tę gramatykę:

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

używania wcięcia zamiast szelek do wyznaczenia klocki, i jeszcze dostać taki sam efekt?

(Użyj http://pegjs.majda.cz/online przetestować tę gramatykę z następującego kodu: a{bcd{zyx{}}})

Odpowiedz

18

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(); } 

Wejście:

a 
    b 
    c 
    d 
    z 
    y 
    x 

wyjściowa:

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

Nie można parsować pustego obiektu (ostatnio x), jednak powinno być łatwe do rozwiązania. Tutaj znajduje się reguła SAMEDENT, która powiedzie się, gdy poziom wcięć nie uległ zmianie. INDENT i DEDENT zmiana bieżącego wcięcia bez zmiany pozycji w tekście pos = offset.

+0

Naprawdę doceniam tego anwsera. Jak możesz wymyślić tę metodę? – jiyinyiyong

+0

Jeśli skopiuję/wkleję to bezpośrednio do http://pegjs.majda.cz/online, to się nie skompiluje. Po kilku poprawkach nie jest jasne, jak je "naprawić". – Clearly

+0

Po przetestowaniu tego fragment kodu kompiluje się i generuje oczekiwaną wydajność. Nie wiesz, jakie błędy tam trafiłeś. – chakrit