Reindent Java / C / C ++ / etc. kod

10

Napisz program, który dodaje lub usuwa białe znaki, aby ładnie sformatować kod. Reguły dotyczące tego, jak powinien wyglądać kod po zakończeniu:

  • Żadna linia nie powinna zawierać więcej niż jednego z {i }.
  • {Powinny zawsze być ostatnią rzeczą, na linii.
  • }Powinny zawsze być tylko rzeczą na linii (oprócz spacji, że jest przed nim).
  • Ilość białych znaków przed każdą linią powinna być stałą wielokrotnością bieżącej liczby zagnieżdżeń. (Możesz użyć dowolnej wcięcia, o ile się nie zmienia).
  • Nie należy wstawiać ani usuwać białych znaków, które nie przyczyniają się do spełnienia jednej z tych zasad.

Liczba zagnieżdżeń w pierwszym wierszu wynosi 0. Liczba zagnieżdżeń w każdej innej linii to liczba zagnieżdżeń poprzedniej linii, plus jeden, jeśli poprzednia linia zawiera a {, minus jeden, jeśli bieżąca linia zawiera a }.

{a }wewnątrz literałów ciągowych i komentarzy nie liczą się powyższe reguły. Dosłowny ciąg znaków to tekst zawarty w pojedynczych lub podwójnych cudzysłowach, przy czym pojedyncze lub podwójne cudzysłowy z nieparzystą liczbą odwrotnych ukośników bezpośrednio przed nimi nie są interpretowane jako koniec literału ciągowego. Komentarz to tekst zawarty w /*i */lub tekst przechodzący od //końca linii. W linii wielu znaczników początku komentarza liczy się tylko pierwszy. Komentarze nie są analizowane wewnątrz literałów łańcuchowych.

Przykłady

    main() {printf("Hello!"); // I don't care about the world...
        }

becomes:

main() {
    printf("Hello!"); // I don't care about the world...
}




int main(){
    puts("a");
        puts("b");
}

becomes:

int main(){
    puts("a");
    puts("b");
}


main()
{ printf("{"); /* }
} */
     printf("}//}"); ///*
    }

becomes:

main()
{
    printf("{"); /* }
} */
    printf("}//}"); ///*
}


int test[] = {1, 2, 3};

becomes:

int test[] = {
    1, 2, 3
}
;
tbodt
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Dennis

Odpowiedzi:

6

JavaScript (ES6), 376 373 378 393 bajtów

To było ... całkiem wyzwanie ...

Daj mi znać, jeśli coś jest nie tak z wyjściem, chociaż nie mogłem znaleźć niczego, nie mogę znaleźć niczego więcej.

Wersja bez golfa

Kod napisałem do gry w golfa, więc zobaczmy, jak to idzie ...

ETHprodukcje
źródło
wygląda mi dobrze
tbodt
Grałem w golfa, gdy go napisałem, co oznacza, że ​​jesteś prawdziwym golfistą ...
Erik the Outgolfer
4

JavaScript (ES6), 260 259 bajtów

Analizuje wprowadzany znak po znaku. Wykorzystuje wcięcie 4 spacji.

s=>s.replace(/[^]/g,(x,n)=>(p=s[n-1],a=!l&!c&!e,l|x!='/'?a&x=='*'&p=='/'?c=x:!c&!e&x=='"'?(l^=1,x):x==`
`?(i=e=0,x):a&x=='}'?d--&&i?`
`+x:i=x:a&x=='{'?s[i=!++d,n+1]==`
`?x:x+`
`:i?x:x==' '?'':' '.repeat(!c*d*4,i=1)+x:p==x?e=x:!e&p=='*'?(c=0,x):x),d=i=l=c=e=0)

Jest to nadal PWT i został zasadniczo przetestowany tylko na podanych przykładach. Jeśli znajdziesz jakiś błąd, daj mi znać w komentarzach.

Stan analizatora składni jest w pełni opisany przez następujące zmienne:

  • d → aktualna głębokość zagnieżdżenia
  • i → flaga informująca, że ​​znajdujemy się „wewnątrz” kodu (tj. Za wiodącymi spacjami wiersza)
  • l → flaga literału łańcucha znaków
  • c → blokuj flagę komentarza
  • e → flaga komentarza liniowego

Obowiązkowa wersja z wcięciem

s => s.replace(
  /[^]/g,
  (x, n) => (
    p = s[n - 1],
    a = !l & !c & !e,
    l | x != '/' ?
      a & x == '*' & p == '/' ?
        c = x
      :
        !c & !e & x == '"' ?
          (l ^= 1, x)
        :
          x == `\n` ?
            (i = e = 0, x)
          :
            a & x == '}' ?
              d-- && i ? `\n` + x : i = x
            :
              a & x == '{' ?
                s[i = !++d, n + 1] == `\n` ? x : x + `\n`
              :
                i ?
                  x
                :
                  x == ' ' ? '' : ' '.repeat(!c * d * 4, i = 1) + x
    :
      p == x ?
        e = x
      :
        !e & p == '*' ? (c = 0, x) : x
  ),
  d = i = l = c = e = 0
)

Przypadki testowe

Arnauld
źródło