2009-08-24 9 views
8

Próbuję parsować CSS, lub przynajmniej podstawy, używając ANTLR. Mam jednak kilka problemów z moimi zasadami dotyczącymi leksykonu. Problem polega na niejednoznaczności między selektorami ID a szesnastkowymi wartościami kolorów. Korzystanie z uproszczoną gramatykę dla jasności, należy rozważyć następujące dane wejściowe:Parsowanie CSS z ANTLR - przypadki krawędzi

#bbb { 
    color: #fff; 
} 

oraz następujące zasady parsera:

ruleset : selector '{' property* '}'; 
selector: '#' ALPHANUM; 
property: ALPHANUM ':' value ';' ; 
value: COLOR; 

i te znaki Lexer:

ALPHANUM : ('a'..'z' | '0'..'9')+; 
COLOR : '#' ('0'..'9' | 'a'..'f')+; 

to nie będzie działać, ponieważ #bbb jest tokenem jako token COLOR, mimo że powinien to być selektor. Jeśli zmienię selektor, aby nie zaczynał się od znaku szesnastkowego, działa dobrze. Nie jestem pewien, jak rozwiązać ten problem. Czy istnieje sposób, aby powiedzieć ANTLR, aby traktować określony token tylko jako żeton KOLORU, jeśli jest on w określonej pozycji? Powiedzmy, że jeśli jest to zasada własności, mogę bezpiecznie założyć, że to jest token koloru. Jeśli nie, potraktuj to jako selektor.

Każda pomoc zostanie doceniona!


Rozwiązanie: Okazuje się, że próbowałem zrobić zbyt wiele w gramatyce, którą prawdopodobnie powinienem poradzić sobie w kodzie za pomocą AST. CSS ma zbyt wiele niejednoznacznych tokenów, aby niezawodnie podzielić się na różne tokeny, więc podejście, którego teraz używam, to w zasadzie tokenizacja znaków specjalnych takich jak "#", ".", ":" I nawiasy klamrowe oraz przetwarzanie postów w kod konsumenta. Działa znacznie lepiej i łatwiej radzić sobie z przypadkami skrajnymi.

Odpowiedz

8

Spróbuj przesunąć # w pliku Lexer od koloru do własnej rzeczy, jako takich:

LLETTERS: ('a'..'z') 
ULETTERS: ('A'..'Z') 
NUMBERS: ('0'..'9') 
HASH : '#'; 

Następnie w regułach parsera, można zrobić to tak:

color: HASH (LLETTERS | ALPHANUM)+; 
selector: HASH (ULETTERS | LLETTERS) (ULETTERS | LLETTERS | NUMBERS)*; 

itd.

Pozwala to określić gramaturę różnicy, którą można z grubsza określić jako kontekstową, w stosunku do leksykalnej, którą można z grubsza określić jako wygląd. Jeśli znaczenie czegoś zmienia się w zależności od tego, gdzie jest, różnica ta powinna być określona w gramatyce, a nie w lexer.

Uwaga: kolory i selektor mają identyczną definicję. Lexers są zwykle oddzielnym etapem od modułu, który tłumaczy wejściowy ciąg na gramatykę, więc nieważne jest posiadanie niejednoznacznego leksykonu (jak wskazano, bbb może być w postaci szesnastkowej lub może być łańcuchem liter małej litery). Dlatego sprawdzanie poprawności danych musi być wykonywane w innym miejscu.

+0

To nadal nie działa. Problem polega na tym, że bbb (lub cokolwiek, co zaczyna się od 0..9 | a..f) zostanie zkastrowane jako HEXSTRING. Zapobiegnie to dopasowaniu #bbb jako selektora. –

+0

cóż, właściwie tam byłem. Wierzę, że skoro bbb jest zarówno poprawnym ciągiem, jak i poprawnym szesnastkiem, konieczne będzie sprawdzenie poprawności danych po stronie oprogramowania. –

+0

Tego się boję. Mam nadzieję, że istnieje tu pewien guru antlr na stackoverflow, który może udowodnić, że się mylisz:/ –

2

Aby Ditto co Walt powiedział Appendix G. Grammar of CSS 2.1 mówi lex HASH, a następnie (w zależności od jego położenia w stosunku do innych tokena) do analizowania HASH albo jako simple_selector lub jako hexcolor.

lexer określa następujące żeton ...

"#"{name}  {return HASH;} 

... i gramatyki obejmuje następujące zasady ...

hexcolor 
    : HASH S* 
    ; 

simple_selector 
    : element_name [ HASH | class | attrib | pseudo ]* 
    | [ HASH | class | attrib | pseudo ]+ 
    ; 

Oznacza to, że parser oparty na gramatyce pozwoliłby na użycie heksadoku innego niż heksadecymalny.

Wykryłabym nie hexex hexcolor później w kodzie, który analizuje/interpretuje drzewo składni lexed + parsowane.

+0

Tak, znam ten załącznik. Używam go jako jednego z moich źródeł do gramatyki, którą buduję. Nie rozwiązuje to jednak problemu dla mnie :( –

+0

@Erik: Czy zapoznałeś się z gramatyką CSS dostępną pod adresem http://www.antlr.org/grammar/list –

+0

Tak, przyjrzałem się Gramatyka CSS 3, pokazuje ten sam błąd: –

0

Aby podjąć decyzję z wielu alternatyw, ANTLR ma dwie opcje,

  • składniowe predykaty
  • semantyczne predykaty

To z antlr lib gramatyki (CSS2.1 g):

 
simpleSelector 
    : elementName 
     ((esPred)=>elementSubsequent)* 

    | ((esPred)=>elementSubsequent)+ 
    ; 

esPred 
    : HASH | DOT | LBRACKET | COLON 
    ; 

elementSubsequent 
    : HASH 
    | cssClass 
    | attrib 
    | pseudo 
    ; 

cssClass 
    : DOT IDENT 
    ; 

elementName 
    : IDENT 
    | STAR 
    ; 

Jest to używane w przypadku predykatów składniowych.

Link do gramatyki: http://www.antlr.org/grammar/1240941192304/css21.g

0

prostu przyszedł tutaj przez googling i znaleźć dobre źródło, prawdziwe implimentation. Dla tych, którzy przychodzą i szukają pełnego gramatyki CSS Antlr, spójrz na gramatykę this. To może dać ci pomysł lub możesz go bezpośrednio użyć.