2009-04-30 10 views
19

Miałem nadzieję napisać własny zakreślacz składni do letniego projektu, nad którym mam zamiar pracować, ale nie jestem pewien, jak napisać własny zakreślacz składni.Pisanie znacznika składni

Wiem, że istnieje wiele implementacji tam, ale chciałbym dowiedzieć się o wyrażeń regularnych i jak działa podświetlanie składni.

Jak działa podświetlanie składni i jakie są dobre referencje do ich tworzenia? Czy podświetlanie składni skanuje każdy znak po wpisaniu lub skanuje obszar dokumentu/tekstu jako całość po wpisaniu każdego znaku?

Każdy wgląd byłby bardzo doceniony.

Dzięki.

PS: I planuje pisania w języku ActionScript

Odpowiedz

17

Słowniki składni mogą działać na dwa bardzo ogólne sposoby. Pierwszy implementuje pełny lexer i parser dla podświetlonego języka, dokładnie identyfikując typ każdego tokena (słowo kluczowe, nazwa klasy, nazwa instancji, typ zmiennej, dyrektywa preprocesora ...). Zapewnia to wszystkie informacje potrzebne do dokładnego zaznaczenia kodu zgodnie z pewną specyfikacją (słowa kluczowe na czerwono, nazwy klas na niebiesko, co ty).

Drugi sposób jest podobny do tego, który stosuje Google Code Prettify, gdzie zamiast implementować jeden lexer/parser na język, użyto paru bardzo ogólnych parserów, które mogą wykonać przyzwoitą pracę na większości składni. Na przykład ten zakreślacz będzie w stanie analizować i podkreślać w miarę dobrze każdy język podobny do języka C, ponieważ jego lexer/parser może identyfikować ogólne składniki tego rodzaju języków.

Ma to również tę zaletę, że w rezultacie nie trzeba jednoznacznie określać języka, ponieważ silnik sam zdecyduje, które z jego generycznych analizatorów może wykonać najlepszą pracę. Minusem jest oczywiście to, że podświetlanie jest mniej doskonałe niż w przypadku używania parsera specyficznego dla języka.

+3

Zacząłeś mówić, że zakreślacze działają na dwa ogólne sposoby, ale potem, chyba że źle zrozumiałem, nie wyjaśniłeś drugiej strony. – Marplesoft

+6

@Marplesoft, jak rozumiem, pisanie lexera i parsera na język jest pierwszą metodą, a pisanie generycznego lexera i parsera jest na drugim miejscu. – yasar

2

należy traktować cały dokument jako całości na początku. Myślę, że (nie będąc ekspertem) chcesz rozbić każdy token i stworzyć drzewo parsowania.

Jeśli masz wszystkie ustawienia, możesz najpierw uruchomić analizator składni za każdym razem, gdy wpiszesz nową. To może być wystarczająco dobre dla twojego usecase, ale jeśli chcesz zachować rzeczy szybko, będziesz musiał wprowadzić modyfikacje w drzewie parse jako dostajesz więcej informacji.

+0

Co jesteś w zasadzie budowy, nazywa się Lexer (wierzę) – Evert

+0

Zgadzam się, że dokument powinien być traktowany jako całości w po pierwsze, ale trudno powiedzieć, czy spełnia to specyfikacje oparte na niejasnym opisie projektu. – Tony

3

To może pomóc, jeśli wyjaśnisz, do czego służy ten zakreślacz składni. Jeśli piszesz to w actionscript, to czy masz pomysł na pole tekstowe w filmie flash i podświetlić składnię po naciśnięciu przycisku "prześlij"? A może chcesz przeczytać tekst z jakiegoś webservice, a następnie wyświetlić podświetloną składnię? ... ciężko mi pomóc, ponieważ trudno mi sobie wyobrazić, co robisz

Jednak wyróżnienie syntaktyczne czyta się w tekście, a następnie porównuje linie kodów z niektórymi regex'ami, które pomagają wyróżnić składnię co oznaczają słowa. Na przykład, może to odczytać słowa „funkcja” lub „int” jako słowa zastrzeżone i zastąpić je tekście html:

<span class="reserved">function</span>, <span class="reserved"></span> 

zakładając, że masz css i chcesz słów zastrzeżonych w kolorze czerwonym,

.reserved{ 
    color: #ff0000; 
} 

To jest podstawowa koncepcja i możesz chcieć wziąć pomysły od geshi, ponieważ możesz zobaczyć źródło.

+0

Niestety, nie wyjaśniłem więcej. Planuję wdrożenie edytora tekstowego współpracującego z Adobe Flex. Chcę mieć TextArea lub podobny komponent wprowadzania tekstu ... wtedy, gdy użytkownik wpisał, na przykład kod Java, kod, który wpisywali, zostałby podświetlony. Podobnie jak wszelkie IDE z podświetlaniem składni. –

4

W StackOverflow podcast number 50 Steve Yegge mówi trochę o swoim projekcie, aby stworzyć ogólny mechanizm wyróżniający. Nie jest to gotowy produkt i może bardziej wyszukany, niż ci się wydaje, ale może być coś ciekawego.

2

Niestety, nigdy nie używałem Actionscript, więc nie mogę pomóc z tą częścią.

Poza tym dobrym początkiem pisania zakreślacza składni byłoby spojrzenie na istniejące. Na przykład vim ma pliki składni w postaci zwykłych plików tekstowych, więc możesz na nie spojrzeć. Jest tam kilka wyrażeń regularnych (wyrażenia regularne występują w różnych smakach, ale nie są tak różne ...), więc dla tej części możesz rzucić okiem na jakąś książkę.

Osobiście uważam, że Beginning regular expressions jest niezły. Mastering regular expressions jest również przydatny w bardziej zaawansowanych przedmiotach. Regular expressions pocket reference jest natomiast przyjemny do określenia różnic we wspomnianych wyżej smakach, ponieważ zawiera również rozdział dotyczący regex vima.

2

dobry początek jedno podejście do tego jest Udacity course CS262. Tytuł buduje przeglądarkę internetową, ale tak naprawdę klasa skupia się dokładnie na problemach, których szukasz - jak analizować i porównywać zestaw tekstu. W twoim przypadku użyjesz tej informacji do wyróżnienia. Po prostu to wziąłem i było bardzo dobrze. Kurs jest już "przesadzony", ale filmy i problemy praktyczne/prace domowe są nadal dostępne i dostępne do oglądania.

+0

świetny kurs, ty! – nimrod

2

Budowanie markera składni polega na wyszukiwaniu określonych słów kluczowych w kodzie i nadawaniu im określonego stylu (czcionki, stylu czcionki, koloru itp.). Aby to osiągnąć, musisz zdefiniować listę słów kluczowych specyficznych dla języka programowania, w którym napisany jest kod, a następnie przeanalizować tekst (np. Używając wyrażeń regularnych), znaleźć konkretne tokeny i zastąpić je odpowiednio zaprojektowanymi Tagi HTML.

Bardzo podstawowy highligher napisany w JavaScript będzie wyglądać następująco:

var keywords = [ "public", "class", "private", "static", "return", "void" ]; 
for (var i = 0; i < keywords.length; i++) 
{ 
     var regex = new RegExp("([^A-z0-9])(" + keywords[i] + ")([^A-z0-9])(?![^<]*>|[^<>]*</)", "g"); 
     code = code.replace(regex, "$1<span class='rm-code-keyword'>$2</span>$3"); 
}