AiSD1
Treść zadania projektowego:
Celem zadania jest napisanie prostego silnika przetwarzającego CSS-y. W ramach zadania należy wczytać ze standardowego wejścia sekcje CSS przeplatane sekcjami komend. Sekcje CSS należy sparsować i umieścić w odpowiednich strukturach, sekcje komend należy sparsować i wykonać wypisując na standardowe wyjście ew. rezultaty (po ==). CSS Przetwarzanie rozpoczyna się wczytania deklaracji CSS. CSS jest syntaktycznie poprawny i składa się bloku atrybutów ew. poprzedzonych selektorami. Brak selektorów jest legalny (oznaczałby atrybuty aplikowane do wszystkiego). Selektory (selectors) są separowane przecinkami. Dopuszczalne są selektory legalne dla CSS, ale można założyć, że nie zawierają znaków przecinka ani nawiasów klamrowych. Blok atrybutów ujęty jest w nawiasy klamrowe Atrybuty są oddzielone średnikami i składają się z nazwy (property) i wartości (value) oddzielonych dwukropkiem. Po ostatnim atrybucie w bloku może, ale nie musi nastąpić średnik. Jako wartości atrybutów mogą występować legalne dla CSS konstrukcje, jednak dla uproszczenia można bezpiecznie założyć, że ew. napisy nie są złośliwe tj. nie zawierają escapowanych znaków cudzysłowu, nawiasów klamrowych lub średników. Jeśli konkretny atrybut (nazwa) w bloku występuje więcej niż raz należy potraktować to jako jedno wystąpienie, przy czym znacząca jest ostatnia wartość). Zarówno selektory, nazwy atrybutów jak i wartości atrybutów nie wymagają interpretacji semantycznej tj. traktujemy je (po odrzuceniu skrajnych białych znaków, jako wartość. Tj. np. 'margin-left : 8px', 'margin: 4px 7px 4px 7px' traktujemy jako oddzielne, niezwiązane atrybuty o nazwach odpowiednio 'margin-left' i 'margin' i wartościach '8px' oraz '4px 7px 4px 7px' Podobnie, selektory są traktowane jako wartość i nie wymagają interpretacji tj. np.: 'h1' i 'h1.theme' traktujemy jako oddzielne, niepowiązane selektory. Uproszczenie: CSS nie zawiera komentarzy, ani selektorów typu @, bloki nie mogą się zagnieżdżać. Dla potrzeb większości testów (bez dużej straty można założyć, że żaden selektor ani atrybut nie jest podzielony na kilka linii (ciągle w jednej linii może być kilka separatorów/ i lub atrybutów). Komendy. W poniższych komendach i oraz j to dodatnie liczby całkowite (mieszczą się w int), natomiast n to legalna nazwa atrybutu. ???? – początek sekcji komend; **** - wznów czytanie CSS; ? – wypisz liczbę sekcji CSS; i,S,? – wypisz liczbę selektorów dla sekcji nr i (numery zaczynają się od 1), jeśli nie ma takiego bloku pomiń; i,A,? - wypisz liczbę atrybutów dla sekcji nr i, jeśli nie ma takiego bloku lub sekcji pomiń; i,S,j – wypisz j-ty selector dla i-tego bloku (numery sekcji oraz atrybutów zaczynają się od 1) jeśli nie ma sekcji lub selektora pomiń; i,A,n – wypisz dla i-tej sekcji wartość atrybutu o nazwie n, jeśli nie ma takiego pomiń; n,A,? – wypisz łączną (dla wszystkich bloków) liczbę wystąpień atrybutu nazwie n. (W ramach pojedynczego bloku duplikaty powinny zostać usunięte na etapie wczytywania). Możliwe jest 0; z,S,? – wypisz łączną (dla wszystkich bloków) liczbę wystąpień selektora z. Możliwe jest 0; z,E,n – wypisz wartość atrybutu o nazwie n dla selektora z, w przypadku wielu wystąpień selektora z bierzemy ostatnie. W przypadku braku pomiń; i,D,* - usuń całą sekcję nr i (tj. separatory+atrybuty), po poprawnym wykonaniu wypisz deleted; i,D,n – usuń z i-tej sekcji atrybut o nazwie n, jeśli w wyniku operacji pozostaje pusta sekcja powinna zostać również usunięta (wraz z ew. selektorami), po poprawnym wykonaniu wypisz deleted. Uwagi implementacyjne: Selektory oraz atrybuty powinny być przechowywane jako listy. Poszczególne sekcje CSS powinny być przechowywane w liście dwustronnej (aby efektywnie realizować komendę E – ostatnie wystąpienie atrybutu). Aby lepiej wykorzystać pamięć lista powinna obejmować tablicę T=8 struktur reprezentujących blok (gdzie T jest stałą możliwą do zmiany w czasie kompilacji) oraz licznik zajętych aktualnie struktur (z uwagi na ew. kasowanie elementów). Liczniki warto wykorzystać dla przyśpieszenia operacji parametryzowanych numerem komórki tj. i. Przy alokowaniu nowego węzła tworzona jest tablica T Elementowa. Przy dodawaniu elementów, o ile jest wolne miejsce w węźle listy, należy je wykorzystać zanim alokowane zostaną nowe węzły. Jeżeli w przypadku usuwania elementów pozostanie pusta tablica należy węzeł usunąć. Nie trzeba przesuwać elementów miedzy węzłami, łączyć węzłów itd. Przykład: #breadcrumb { width: 80%; font-size: 9pt; } h1, body { min-width: 780px; margin: 0; padding: 0; font-family: "Trebuchet MS", "Lucida Grande", Arial; font-size: 85%; color: #666666; } h1, h2, h3, h4, h5, h6 {color: #0066CB;} ???? ? 1,S,? 1,S,1 1,A,? 2,A,font-family h1,S,? color,A,? h1,E,color 1,A,padding 1,D,* ? 2,D,color ? **** h1, h2, h3, h4, h5, h6 {color: #0066FF;} ???? ? Wynik: ? == 3 1,S,? == 1 1,S,1 == #breadcrumb 1,A,? == 2 2,A,font-family == "Trebuchet MS", "Lucida Grande", Arial h1,S,? == 2 color,A,? == 2 h1,E,color == #0066CB 1,D,* == deleted ? == 2 2,D, color == deleted ? == 1 ? == 2