Konwertowanie pliku .pas do .html zkolorowaniem składni.

0

Witam mam do zrobienia program na zaliczenie z pascala,a jego treść to:
//Konwerter plików napisanych w języku Pascal do HTML z kolorowaniem składni
Napisz program, który na podstawie pliku z kodem w języku Pascal stworzy plik o formacie HTML.
Program powinien jako parametr wywołania pobierać ścieżkę do pliku źródłowego oraz wynikowego.
Dodatkowo program powinien wykrywać słowa kluczowe i w pliku HTML zmieniać ich kolor. Należy
zadbać również o poprawne formatowanie tekstu, zgodne ze składnią języka Pascal. //

Mój aktualny kod to:

program program1;

uses crt;

var
  i:integer;
  plik1,plik2:text;
  tekst:string;
  tab:array[1..1000] of char;
  a:char;
begin

  assign(plik1,'mojprogram.pas');      //plik z ktorego odczytujemy
  Reset(plik1);
  i:=1;

  repeat
  read(plik1,tab[i]);
  inc(i);


  if eoln(plik1) then         //   gdy na koncu wiersza wpisuj polecenie <br>
    begin
     tab[i+1]:='<';
     tab[i+2]:='b';
     tab[i+3]:='r';
     tab[i+4]:='>';
     inc(i,5);
     read(plik1,a);
    end;


  until eof(plik1);

  close(plik1);

  assign(plik2,'D:\Documents and Settings\Venom\Pulpit\nowy\plik.html');       //plik do ktorego zapisujemy
  i:=1;
  Rewrite(plik2);
   repeat
     if ((tab[i]='b') and (tab[i+1]='e') and (tab[i+2]='g') and (tab[i+3]='i') and (tab[i+4]='n')) then
       begin
       write(plik2,'<b>');

       end;


     write(plik2,tab[i]);
     inc(i);
   until i=1000;
  close(plik2);


end.        

I potrzebowałbym pomocy w kwestii wyszukiwania wzorców w tekście i nadawania im konkretnych cech, takich jak pogrubienie czy też kolorowanie, w linijce:

if ((tab[i]='b') and (tab[i+1]='e') and (tab[i+2]='g') and (tab[i+3]='i') and (tab[i+4]='n')) then
       begin
       write(plik2,'<b>');

       end; 

wyszukuje w tekście słowa 'begin' i daje na początku znacznik <b>, ale jak umieścić na koncu begin'a </b>?
Proszę o pomoc ; )

1
tab[i+1]:='<';
     tab[i+2]:='b';
     tab[i+3]:='r';
     tab[i+4]:='>';
     inc(i,5);

What the...

if ((tab[i]='b') and (tab[i+1]='e') and (tab[i+2]='g') and (tab[i+3]='i') and (tab[i+4]='n')) then

Facepalm.

Zlituj się nad sobą i wczytuj to wierszami. Potem można zrobić Pos żeby wyszukać ciąg i go odpowiednio oznaczyć albo nawet użyć StringReplace.

, ale jak umieścić na koncu begin'a
</b>
?

No właśnie temu się nie stosuje takich rozwiązań jak twoje, bo to się mija z celem.

0

Moje nieogarnięcie wynika z tego że z programowaniem w pascalu mam do czynienia dopiero od półtorej miesiąca i dopiero pierwszy raz przysiadam na dłużej do jakiegoś programu.

1

Ja na Twoim miejscu napisałbym tokenizer, a potem wykrywał poszczególne tokeny i odpowiednio dobierał kolorowanie.
Pomogłoby to także w przypadku np.składni FPC var &begin: integer, by begin nie byłoby wykrywane jako słowo kluczowe (podobnie bodajże ze generic, w typach może być rozumiane jako deklaracja typu generycznego, lecz tak samo może być nazwana zmienna) i w przypadku paru innych wyjątków (Lazarus posiada coś takiego, o ile się nie mylę).
Poza tym byłoby łatwo rozszerzalne o nowe konstrukcje i nie trzeba byłoby się bawić w rzeczy stylu if ((tab[i]='b') and (tab[i+1]='e') and (tab[i+2]='g') and (tab[i+3]='i') and (tab[i+4]='n')) then :P

1

Nie trzeba bardzo kombinować, wystarczy utworzyć macierz z rozpoznawanymi słowami, po czym fynkcją PosEx w pętli sprawdzać czy dane słowo istnieje w łańcuchu i jeśli tak - procedurą Insert wstawiać poszczególne znaczniki i wyszukiwać dalej pod kątem innych słów aż do końca łańcucha, gdy PosEx zwróci 0;

Rozwiązanie może i nie mistrzowskie, ale łatwe do implementacji, a biorąc pod uwagę fakt, że nie bardzo umiesz to zrobić będzie dla Ciebie dość proste do wykonania;

Dodatkowo program powinien wykrywać słowa kluczowe i w pliku HTML zmieniać ich kolor.

Czy program ma jedynie rozpoznawać słowa kluczowe i je ozdabiać, czy inne także (jak liczby, nawiasy itd.)?

Należy zadbać również o poprawne formatowanie tekstu, zgodne ze składnią języka Pascal.

Czy program powinien formatować kod z uwzględnieniem jedynie wcięć, czy ma wykonywać więcej czynności?

0

Nie trzeba bardzo kombinować, wystarczy utworzyć macierz z rozpoznawanymi słowami, po czym fynkcją PosEx w pętli sprawdzać czy dane słowo istnieje w łańcuchu i jeśli tak - procedurą Insert wstawiać poszczególne znaczniki i wyszukiwać dalej pod kątem innych słów aż do końca łańcucha, gdy PosEx zwróci 0;

Używanie wbudowanych funkcji jest zdecydowanie złym pomysłem:

Program Foo;
Var Str: String;
Begin
 Str := 'Hello begin end; world generic x: var string integer';
 (*
  begin
  if  ; end
 *)
 // type x = bitpacked record
 Writeln(Str);
End;

Jak już, to wypadałoby napisać własne funkcje, które będą pomijać komentarze oraz stringi.

0

@Patryk27 @furious programming ja nie wiem czy wiecie ale pytacz od niedawna programuje więc wątpię czy wasze skomplikowane wywody się przydadzą. Jego celem nie jest napisanie kolorowacza składni do Lazarusa (który jak łatwo się domyślić nie jest prosty), a prostego upiększacza kodu.

Moje nieogarnięcie wynika z tego że z programowaniem w pascalu mam do czynienia dopiero od półtorej miesiąca i dopiero pierwszy raz przysiadam na dłużej do jakiegoś programu.

A moje ogarnięcie wynika z tego że z programowaniem z pascalu mam do czynienia od paru lat i już milionowy raz przysiadam na dłużej do jakiegoś programu. Tylko co to ma do tematu?! Przeanalizuj odpowiedzi, popracuj nad kodem (dużo pracy potrzeba), pogoogluj i udziel odpowiedzi która rozwinie wątek.

0
-321oho napisał(a)

Jego celem nie jest napisanie kolorowacza składni do Lazarusa (który jak łatwo się domyślić nie jest prosty), a prostego upiększacza kodu.

Zauważ, że program z założenia nie jest taki znowu prosty, zważywszy na wyjątki jakimi są komentarze i wartości łańcuchów, które trzeba pomijać; Początkujący może mieć z tym problem, więc ciężko podać jakieś sensowne rozwiązanie, które newbie będzie potrafił zaimplementować;

Z najprostszych rozwiązań nasuwa mi się ręczne przeszukiwanie linii bez PosEx, sprawdzanie bieżącego znaku czy to początek słowa kluczowego, czy komenatrza, czy wartości łańcucha i odpowiednie reagowanie; Do wstawiania znaczników - Insert i przestawianie licznika pętli na koniec słowa kluczowego + długość znacznika po ich dodaniu; Wykorzystanie pętli while .. do;

Jeśli masz jakieś lepsze rozwiązanie - pochwal się :]

1

Jeśli masz jakieś lepsze rozwiązanie - pochwal się

Mówiłem już o StringReplace? Proste i będzie w miarę działać póki ktoś nie będzie usiłował oszukać tego mechanizmu (tak jak @Patryk27 i jego zmienne nazywane słowami kluczowymi).

Zauważ, że program z założenia nie jest taki znowu prosty, zważywszy na wyjątki jakimi są komentarze i wartości łańcuchów, które trzeba pomijać; Początkujący może mieć z tym problem, więc ciężko podać jakieś sensowne rozwiązanie, które newbie będzie potrafił zaimplementować;

Wiem że problem nie jest taki prosty, ale wy szukacie metody idealnej. Zapewne tego on nie musi mieć.

To nie są skomplikowane sposoby, tylko tak brzmią; Kilka prostych funkcji z VCL, Google i trochę pomyślunku - nie trzeba być do tego pro haksiorem :P

A patrzyłeś na piękną tablicę charów pytacza? Już o porównaniach nie wspominając.

0

Ze wszystkich tu podanych porad zrobiłem taki oto program:

program program1;

uses crt, Dialogs, SysUtils;
     function wymiana(a,b,c:string): string;
        var OldStr, NewStr: String;
       begin


         OldStr := a;
         NewStr := b;
         wymiana:=StringReplace(c, OldStr, NewStr, [rfReplaceAll]);
       end;
var
  i,j:integer;
  plik1,plik2:text;
  zmienna_pytajaca1, zmienna_pytajaca2 : string;
  tab:array[1..1000] of string;
begin
  i:=1;
  write('Podaj sciezke do pliku wejsciowego z rozszerzeniem .pas: ');
  readln(zmienna_pytajaca1);
  write('Podaj sciezke do pliku wyjsciowego z rozszerzeniem .html: ');
  readln(zmienna_pytajaca2);
  assign(plik1,zmienna_pytajaca1);      //plik wejsciowy
  Reset(plik1);
   while not eof(plik1) do              // wykonuje polecenia do konca pliku
    begin
        readLN(plik1,tab[i]);


        tab[i]:=wymiana('for','<b>for</b>',tab[i]);
        tab[i]:=wymiana('begin','<b>begin</b>',tab[i]);
        tab[i]:=wymiana('program','<b>program</b>',tab[i]);
        tab[i]:=wymiana('if','<b>if</b>',tab[i]);
        tab[i]:=wymiana('end.','<b>end.</b>',tab[i]);
        tab[i]:=wymiana('end;','<b>end;</b>',tab[i]);
        tab[i]:=wymiana('else','<b>else</b>',tab[i]);
        tab[i]:=wymiana('uses','<b>uses</b>',tab[i]);
        tab[i]:=wymiana('var','<b>var</b>',tab[i]);
        tab[i]:=wymiana('repeat','<b>repeat</b>',tab[i]);
        tab[i]:=wymiana('assign','<b>assign</b>',tab[i]);
        tab[i]:=wymiana('while','<b>while</b>',tab[i]);
        tab[i]:=wymiana('do','<b>do</b>',tab[i]);
        tab[i]:=wymiana('do','<b>do</b>',tab[i]);
        


      inc(i);
    end;
  close(plik1);







  assign(plik2,zmienna_pytajaca2);       //plik wyjsciowy
  Rewrite(plik2);
    writeln(plik2,'<html><pre>');
     for j:=1 to i do writeln(plik2,tab[j]);

  close(plik2);

end. 

W pliku wynikowym html dostaję dokładnie taki sam kod wraz z takimi samymi wcięciami.
Reguły dla pogrubienia słów kluczowych utworzyłem, są one obsługiwane przez funkcję "wymiana"
i mogę w każdym momencie dodawać nowe, niestety nie wiem jak do końca zrobić kolorowanie
w taki sposób, aby tekst który jest pomiędzy apostrofami w funkcji writeln('tekst') był kolorowy.
Liczby też chciałbym aby były kolorowane, no i przydałoby się kolorować również komentarze.

Dziękuję Wam za wyrozumiałość, tak jak już powtarzałem, mój staż w pascalu, jak i w ogóle w
programowaniu jest bardzo krotki, na razie się uczę, stad wynikają niedoskonałości w moim kodzie

1

A co Twój program wygeneruje dla kodu:
if (boolean(1024) = true)
PS: masz ciekawy buffer overflow przy 1001 linijce.
PS2: writeln ( to wg.Ciebie nie to samo co writeln(?

0

Czy ktoś by mi mógł udzielić rady co do kolorowania kodu pomiędzy dwoma apostrofami ?

1

Coś w rodzaju:

Function ParseLine(Line: String): String;
Const Ap = '''';
Var I: Integer;
    Opened: Boolean=False;
Begin
 Result := '';
 For I := 1 To Length(Line) Do
  if (Line[I] = Ap) Then
  Begin
   Opened := not Opened;
   Case Opened of
    True: Result += '<span class="string">';
    False: Result += '</span>';
   End;
  End Else
   Result += Line[I];
End;

Potem jedynie za pomocą CSS zadeklarować coś takiego:

.string
{
 font-color: red;
}

Funkcja po prostu przeszukuje każdy znak ze wczytanej linii, wynik przekazuje jako result funkcji; jeżeli natrafi na apostrof (czyli rozpoczęcie lub zakończenie ciągu znaków) zmienia stan zmiennej wskazującej czy string jest otwarty czy nie (tutaj `Opened`). Jeżeli string został dopiero otwarty, dodajemy ``, a jeżeli zamknięty, to zamykamy ``. Każdy inny znak jest przekazywany do normalnego wyjścia bez zmian. Oczywiście funkcja nie zadziała w przypadku np.konstrukcji `Writeln('something '' lol');`, ale to już zostawiam Tobie to zrobienia ;)
0
Patryk27 napisał(a)

Result += Line[I];

Super że znasz i używasz funkcjonalności którą daje FPC, ale wypada bądź co bądź początkującemu pytaczowi że to jest równoważne z Result:=Result+Line[i];.

0

Mój prawie gotowy kod:

program program1;


uses crt, Dialogs, SysUtils;



Function Kolorowanie(Linia: String): String;        //funkcja kolorujaca tekst pomiedzy apostrofami
 Const Apostrof = '''';
 Var I: Integer;
   opened: Boolean;

Begin
   opened:=False;
   Kolorowanie := '';
    For i := 1 To Length(Linia) Do
     if (Linia[i] = Apostrof) Then
      Begin
       opened := not opened;
        Case opened of
         True: Kolorowanie := Kolorowanie+'&#146<span class="string">';
         False: Kolorowanie := Kolorowanie+'</span>&#146';
        End;
      End Else
   Kolorowanie:=Kolorowanie+Linia[i];
End;


Function zamiana(a,b,c:string): string;             //funkcja do zamiany tekstu(kolorowanie i pogrubianie tekstu)
  var OldStr, NewStr: String;
Begin
  c:=lowercase(c);
  OldStr := a;
  NewStr := b;
  zamiana:=StringReplace(c, OldStr, NewStr, [rfReplaceAll]);
End;


var
  i,j:integer;
  plik1,plik2:text;


  tab:array[1..1000] of string;
begin

  i:=1;

  assign(plik1,'plik.pas');                         //plik wejsciowy(.pas)
  Reset(plik1);
   while not eof(plik1) do                          // petla podmienianiajaca tekst przy pomocy funkcji "zamiana"
    begin
        readLN(plik1,tab[i]);

        tab[i]:=zamiana('>','&gt;',tab[i]);
        tab[i]:=zamiana('<','&lt;',tab[i]);
        tab[i]:=zamiana('for','<b>for</b>',tab[i]);
        tab[i]:=zamiana('begin','<b>begin</b>',tab[i]);
        tab[i]:=zamiana('program','<b>program</b>',tab[i]);
        tab[i]:=zamiana('if','<b>if</b>',tab[i]);
        tab[i]:=zamiana('end.','<b>end.</b>',tab[i]);
        tab[i]:=zamiana('end;','<b>end;</b>',tab[i]);
        tab[i]:=zamiana('else','<b>else</b>',tab[i]);
        tab[i]:=zamiana('uses','<b>uses</b>',tab[i]);
        tab[i]:=zamiana('var','<b>var</b>',tab[i]);
        tab[i]:=zamiana('const','<b>var</b>',tab[i]);
        tab[i]:=zamiana('assign','<b>assign</b>',tab[i]);
        tab[i]:=zamiana('while','<b>while</b>',tab[i]);
        tab[i]:=zamiana('function','<b>function</b>',tab[i]);
        tab[i]:=zamiana('do','<b>do</b>',tab[i]);
        tab[i]:=zamiana('repeat','<b>repeat</b>',tab[i]);
        tab[i]:=zamiana('until','<b>until</b>',tab[i]);
        tab[i]:=zamiana('then','<b>then</b>',tab[i]);
        tab[i]:=zamiana('integer','<b>integer</b>',tab[i]);
        tab[i]:=zamiana('longint','<b>longint</b>',tab[i]);
        tab[i]:=zamiana('shortint','<b>shortint</b>',tab[i]);
        tab[i]:=zamiana('byte','<b>byte</b>',tab[i]);
        tab[i]:=zamiana('word','<b>word</b>',tab[i]);
        tab[i]:=zamiana('real','<b>real</b>',tab[i]);
        tab[i]:=zamiana('string','<b>string</b>',tab[i]);
        tab[i]:=zamiana('char','<b>char</b>',tab[i]);
        tab[i]:=zamiana('0','<font color=red>0</font>',tab[i]);
        tab[i]:=zamiana('1','<font color=red>1</font>',tab[i]);
        tab[i]:=zamiana('2','<font color=red>2</font>',tab[i]);
        tab[i]:=zamiana('3','<font color=red>3</font>',tab[i]);
        tab[i]:=zamiana('4','<font color=red>4</font>',tab[i]);
        tab[i]:=zamiana('5','<font color=red>5</font>',tab[i]);
        tab[i]:=zamiana('6','<font color=red>6</font>',tab[i]);
        tab[i]:=zamiana('7','<font color=red>7</font>',tab[i]);
        tab[i]:=zamiana('8','<font color=red>8</font>',tab[i]);
        tab[i]:=zamiana('9','<font color=red>9</font>',tab[i]);
        tab[i]:=zamiana(':=','<font color=green>:=</font>',tab[i]);
        tab[i]:=zamiana('ran<b>do</b>m','random',tab[i]);
        tab[i]:=zamiana('ran<b>do</b>mize','randomize',tab[i]);
        tab[i]:=zamiana('(','<b>(</b>',tab[i]);
        tab[i]:=zamiana(')','<b>)</b>',tab[i]);


        tab[i]:=kolorowanie(tab[i]);                //odwolanie do funkcji kolorowanie


      inc(i);
    end;
  close(plik1);








  assign(plik2,'plik.html');                        //plik wyjsciowy(.html)
  Rewrite(plik2);
    write(plik2,'<html><pre><style type="text/css">span.string {color: green;}</style>');
         for j:=1 to i do writeln(plik2,tab[j]);
         writeln(plik2,'</body></html>');

  close(plik2);

end.

Czy mógłby ktoś sprawdzić i zrecenzować ten mój program?
Plus potrzebowałbym jeszcze porady na zrobienie funkcji kolorującej komentarze(// i {})
Próbowałem kolorować komentarze funkcją 'zamiana', ale jak można się domyślić były to kiepskie próby
gdyż nakładały mi się kolory i pogrubienia z innych zamian. Jak wiec zrobić funkcje która w przypadku napotkania '{'
aż to napotkania '}' zignoruje wszystkie dotychczasowe zamiany ?
Ponadto za poradą Patryk27 chciałbym zastosować w swoim programie tablicę dynamiczną i mam pytanie
jak mógłbym policzyć ilość linijek kodu pliku wejściowego ?
Wszelkie uwagi i rady dotyczące kodu mile widziane.
Dziękuję wszystkim za dotychczasową pomoc ; ))

0

GeSHi lub Pygments + obsługa jakimś ShellExecute, lub czymś podobnym :D Albo jakiś lib dla Delphi zawierajace takie funkcje. Niech początkujący programmer nie myśli sobie, że zawsze wszystko trzeba robić na piechotę :)

1

Czy mógłby ktoś sprawdzić i zrecenzować ten mój program?

  1. Na co ci tablica 1000 stringów. Twój algorytm jest na tyle prosty że wystarczy pamiętać jedną linię.
  2. Te zamiany proszą się o jakąś tablicę w których wszystko będzie przechowywane. Najlepiej bez dwóch stringów, bo forma wyjściowa jest zależna od wejścia.
tab[i]:=zamiana('ran<b>do</b>m','random',tab[i]);
tab[i]:=zamiana('ran<b>do</b>mize','randomize',tab[i]);

To jest złe rozwiązanie. Wygląda na to że powinieneś przepisać funkcję zamiana która powinna najpierw skanować listę słów w linii a następnie szukać słów kluczowych (interpunkcja powinna być raczej parsowana oddzielnie). Poza tym to nie jest pełna lista słów kluczowych: http://www.freepascal.org/docs-html/ref/refse3.html#x11-100001.3
4.Twój kolorowacz odwali gdy da się mu plik z niezamkniętym apostrofem.

gdyż nakładały mi się kolory i pogrubienia z innych zamian. Jak wiec zrobić funkcje która w przypadku napotkania '{'
aż to napotkania '}' zignoruje wszystkie dotychczasowe zamiany ?

Pamiętać aktualny stan komentarzy i pomijać parsowanie jeżeli aktywny jest komentarz. Gdy pisałem swój bardzo prosty parser kodu Pascala to po prostu wycinałem cały kod komentarza. Możesz zrobić tak samo jeżeli wcześniej wyślesz go do pliku. Pamiętaj jeszcze że komentarze mogą być na więcej niż jeden wiersz.

Ponadto za poradą Patryk27 chciałbym zastosować w swoim programie tablicę dynamiczną i mam pytanie
jak mógłbym policzyć ilość linijek kodu pliku wejściowego ?

Musisz przejść cały plik (a żeby się cofnąć w pliku testowym trzeba mieć chaksiorskie procedury). Ale na co ci tablica dynamiczna pojęcia nie mam. Możesz mieć parę plików naraz otwartych i pisać na bieżąco.

0

Mój poprawiony kod:
program program1;
uses crt, Dialogs, SysUtils;

Function Kolorowanie(Linia: String): String;         //funkcja kolorujaca tekst pomiedzy apostrofami
 Const Apostrof = '''';
 Var I: Integer;
   opened: Boolean;
Begin
   opened:=False;
   Kolorowanie := '';
    For i := 1 To Length(Linia) Do
     if (Linia[i] = Apostrof) Then
      Begin
       opened := not opened;
        Case opened of
         True: Kolorowanie := Kolorowanie+'&#146<span class="string">';
         False: Kolorowanie := Kolorowanie+'</span>&#146';
        End;
      End Else
   Kolorowanie:=Kolorowanie+Linia[i];
End;

Function zamiana(a,b,c:string): string;              //funkcja do zamiany tekstu(kolorowanie i pogrubianie tekstu)
  var OldStr, NewStr: String;
Begin
  c:=lowercase(c);
  OldStr := a;
  NewStr := b;
  zamiana:=StringReplace(c, OldStr, NewStr, [rfReplaceAll]);
End;

var
  plik1,plik2,Reserved,liczba:text;
  linijka: string;
  SlowoKluczowe: string;
begin
 assign(plik2,'dupa.html');                          //plik wyjsciowy(.html)
  Rewrite(plik2);
    write(plik2,'<html><pre><style type="text/css">span.string {color: green;}</style>');

  assign(Reserved,'ReservedWords.txt');              //matryca slow kluczowych w Pascalu zapisana w pliku ReservedWords.txt
  assign(Liczba,'liczba.txt');
  assign(plik1,'losowa_liczba.pas');                 //plik wejsciowy(.pas)
   reset(plik1);
    while not eof(plik1) do                          // petla podmienianiajaca tekst przy pomocy funkcji "zamiana"
     begin
       readLN(plik1,linijka);
       linijka:=zamiana('<','&lt;',linijka);
       linijka:=zamiana('>','&gt;',linijka);
        Reset(Reserved);
         while not eof(Reserved) do                  //Przyrównywanie linijek kodu do matrycy
         begin
          readLN(reserved,SlowoKluczowe);
           linijka:=zamiana(SlowoKluczowe,'<b>'+SlowoKluczowe+'</b>',linijka);
         end;
        close(Reserved);
          Reset(Liczba);
         while not eof(Liczba) do                    //Przyrównywanie linijek kodu do matrycy liczbowej
         begin
          readLN(Liczba,SlowoKluczowe);
           linijka:=zamiana(SlowoKluczowe,'<font color=red>'+SlowoKluczowe+'</font>',linijka);
         end;
        close(Liczba);

        linijka:=zamiana(':=','<font color=green>:=</font>',linijka);
        linijka:=zamiana('ran<b>do</b>m','random',linijka);
        linijka:=zamiana('ran<b>do</b>mize','randomize',linijka);
        linijka:=kolorowanie(linijka);               //odwolanie do funkcji kolorowanie
        writeln(plik2,linijka);
    end;
    close(plik1);
      writeln(plik2,'</body></html>');
  close(plik2);
end.

1.Usunąłem tablicę i w jej miejsce dałem zmienną 'linijka', na której to na bieżąco są wykonywane wszystkie operacje, tj. odczytywanie z pliku, wszelkie podmiany i kolorowania plus zapis do pliku.
2.Dodałem plik: ReservedWords.txt, w którym to zawarte są słowa kluczowe w Pascalu ze strony: http://www.freepascal.org/docs-html/ref/refsu1.html#x12-110001.3.1
W tym momencie wyszukiwanie słów kluczowych w linijkach kodu jest realizowane przy pomocy tej matrycy. Dodałem również plik liczby.txt, w którym są zawarte liczby od 0 do 9 i w razie wystąpienia w kodzie są kolorowane na czerwono.
3.W dalszym ciągu potrzebowałbym rady co do realizacji kolorowania komentarzy oraz rady co do usuniecia zlych wystapien slow kluczowych jak np. do w randomize...

0
        Reset(Reserved);
         while not eof(Reserved) do                  //Przyrównywanie linijek kodu do matrycy
         begin
          readLN(reserved,SlowoKluczowe);
           linijka:=zamiana(SlowoKluczowe,'<b>'+SlowoKluczowe+'</b>',linijka);
         end;
        close(Reserved);

Mniej wydajne rozwiązanie prawdopodobnie nie istnieje, za każdym razem otwierasz od nowa plik i dla każdej linijki pliku wejściowego skanujesz od nowa listę słów kluczowych! Wczytaj je raz na początku programu do tablicy dynamicznej...

0
Patryk27 napisał(a)

Wczytaj je raz na początku programu do tablicy dynamicznej...

Albo lepiej do jakiegoś TStringList. Wtedy można nawet z automatu ładować i wyszukiwać dane.

Dodałem również plik liczby.txt, w którym są zawarte liczby od 0 do 9 i w razie wystąpienia w kodzie są kolorowane na czerwono.

To jest złe rozwiązanie. Zrób sobie podobną funkcję jak do parsowania apostrofów (może nawet z nią połączyć to?), tylko teraz szukaj czegoś co po znaku typu ;, ma $ i hex lub liczbę i koloruj całość odpowiednio. Twoje aktualne rozwiązanie maluje wszystkie liczby, także te w stringach, wykonaniach funkcji, nazwach zmiennych, procedur itd. (i jest nieefektywne - nie wszystko się wczytuje z pliku a już na pewno nie za każdym razem).

3.W dalszym ciągu potrzebowałbym rady co do realizacji kolorowania komentarzy oraz rady co do usuniecia zlych wystapien slow kluczowych jak np. do w randomize...

Ogarnij procedury operacji na stringach (wyszukiwanie znaków, substringów, kopiowanie danego zakresu znaków itd.) a następnie napisz coś podobnego co będzie ci szukało odpowiednio danych słów kluczowych czy czego tam zapragniesz.

Generalnie to prostym sposobem na rozwiązanie twoich problemów jest napisanie parsera który będzie rozdzielał słowa według znaków spoza zakresu a-z,A-Z,0-9,$. Potem wystarczy sprawdzić czy to słowo kluczowe, obsłużyć i skleić z powrotem. Łatwo będzie to też można rozszerzyć o kolorowanie i pomijanie komentarzy, wystarczy dodać stan który będzie pamiętać czy komentarze są otwarte i odpowiednio obsługiwać wszystko.

0

Nie mam pojęcia jak napisać funkcje które respektowałyby komentarze i zamieniały wszystko co jest w ich wnetrzach na kolor niebieski plus nie uwzglednialyby zadnych innych zamian... Pomoże ktoś ?
Samo kolorowanie potrafię zrobić, ale nie wiem już jak omijać pozostałe zamiany : (
Moje funkcje:

Function komentarze(Linia: String): String;         
 Const ukosniki = '//';
 Var I: Integer;

Begin

   komentarze := '';
    For i := 1 To Length(Linia) Do
     Begin
     if (Linia[i]+Linia[i+1] = ukosniki) Then komentarze := '<span class="string2">//'+komentarze+'<span>'

      Else
   komentarze:=komentarze+Linia[i];
end;
End; 
Function Klamry(Linia: String): String;         //funkcja kolorujaca tekst pomiedzy klamrami
Const
  KlamL = '{';
  KlamR = '}';

 Var I: Integer;

Begin


   Klamry := '';
    For i := 1 To Length(Linia) Do
      Begin
     if (Linia[i] = KlamL) Then Klamry :='<span class="string2">{'+Klamry;
     if (Linia[i] = KlamR) Then Klamry :=Klamry+'}</span>'

       Else
   Klamry:=Klamry+Linia[i];

End;
  end; 
0

Samo kolorowanie potrafię zrobić, ale nie wiem już jak omijać pozostałe zamiany : (

Musisz pamiętać aktywny poziom komentarzy. Jeżeli byś silnik napisał na tokenach to problem byłby prostszy bo wszystko łatwo byłoby ogarniać w jednej pętli.

Masz tu prosty tokenizer, przepisz funkcjonalność programu tak żeby rozróżniał interesujące cie tokeny i łączył je z powrotem:

function Tokenize(s:ansistring):TStringList;
var
  i:integer;
  ss:ansistring;
  lt:byte;
procedure AddType(t:byte;c:char);inline;
begin
  if (t<>lt)and(ss<>'') then
    begin
      result.AddObject(ss,TObject(pointer(lt)));
      lt:=t;
      ss:=c;
    end else ss+=c;
end;
begin
  ss:='';
  lt:=0;
  result:=TStringList.Create;
  for i:=1 to length(s) do case s[i] of
    #32,#8:AddType(1,s[i]);
    '''':AddType(2,s[i]);
    'a'..'z','A'..'Z','0'..'9','$','#':AddType(3,s[i]);
    ';','.',',','(',')','[',']','*','+','-','/':AddType(4,s[i]);
  end;
  if (ss<>'')and(lt<>1) then result.AddObject(ss,TObject(pointer(lt)));
end;

(Jeżeli nie wiesz co to TStringList to sobie najpierw pogoogluj o tym i nie zapomnij zwalniać tej klasy).

0
"TObject(pointer(lt))" i wszystko jest klarowne i proste w rozumieniu :P

Właściwie nie musiałem tego umieszczać ale to upraszcza późniejsze sprawdzanie jaki typ tokenu to jest. Jak piszemy porządny kod to nie będziemy pierniczyć się. W każdym razie pytacz nie musi korzystać z tego ulepszenia.

Btw. zrobiłem sobie mały example do tej funkcji i już ją zpatchowałem (zgadnijcie czemu), ale nie opublikuje tutaj patcha żeby nie było że tylko ja się narobiłem. @pytacz, przeleć sobie procedurę debuggerem, jest błąd który powoduje że pierwsza litera jest zawsze oddzielnie. Poza tym warto dodać jakiś guard który zrobi token również ze znaków których nie wymieniłem (chyba w ogóle paru brakuje? ;) - warto też przenieść co najmniej jeden z nich żeby łatwiej się parsowało tokeny).

0

Niestety, ale o programowaniu obiektowym w Pascalu nie mam zielonego pojęcia, także będę musiał sobie odpuścić tą metodę... :P

0
deathvenom napisał(a):

Niestety, ale o programowaniu obiektowym w Pascalu nie mam zielonego pojęcia, także będę musiał sobie odpuścić tą metodę... :P

Czyli jak czegoś nie wiesz to zamiast się tego nauczyć nie używasz tego? To ciekaw jestem jak się programować nauczyłeś? Może ze względu na oszczędność powinieneś znać tylko goto i if z konstrukcji sterujących?
Ja do Ciebie wyciągnąłem rękę, nawet napisałem króciutki gotowy parser kodu, ale skoro ty tak reagujesz na pomoc to widzę że jednak nie opublikuję tego kodu, bo przecież 'ty musisz sobie odpuścić'. Nie licz już na moją pomoc, bo zamiast docenić mój czas, traktujesz to jakbyś mi płacił.

0

Nie oceniaj mnie po jednej mojej wypowiedzi... Myślałem po prostu, że programowanie obiektowe jest w ogóle czymś niesamowicie skomplikowanym i nie na mój poziom(przynajmniej na razie).
Wystarczyło odpisać, że warto się tego nauczyć czy coś. Poza tym termin oddania tego programu mam na jutro i po prostu bałem się, że czasowo mogę się nie wyrobić z ogarnięciem zjawiska obiektowości.
I jak na mój aktualny poziom ogarnięcia wydaje mi się że nie dałbym rady tak szybko przerobić mój program na takowy tokenizer jaki tu umieściłeś. Ponad to nie wiem jakby zareagowała prowadząca zajęcia na taki skomplikowany kod, gdyż w gruncie rzeczy mieliśmy na razie same podstawy Pascala. Nie myślę o Twojej pomocy jako o jakimś towarze, tylko jako o pomocy doświadczonego kolegi.

0

Nie oceniaj mnie po jednej mojej wypowiedzi...

Jeżeli jest więcej niż jedna wypowiedź to zawsze oceniam po wszystkim.

Myślałem po prostu, że programowanie obiektowe jest w ogóle czymś niesamowicie skomplikowanym i nie na mój poziom(przynajmniej na razie).

Bo ogarnięcie odczytywania danych z TStringList i jego zwalnianie to całe programowanie obiektowe. Rzeczywiście całe programowanie obiektowe to sprawa dla ciebie zbyt skomplikowana.

Wystarczyło odpisać, że warto się tego nauczyć czy coś. Poza tym termin oddania tego programu mam na jutro i po prostu bałem się, że czasowo mogę się nie wyrobić z ogarnięciem zjawiska obiektowości.

Wystarczyło odpisać że nie wiesz czy ogarniesz obiektowość. Nie ma to jak nie widzieć problemu w swojej wypowiedzi.

I jak na mój aktualny poziom ogarnięcia wydaje mi się że nie dałbym rady tak szybko przerobić mój program na takowy tokenizer jaki tu umieściłeś.

Czasu masz mało, nie moja wina że na forum zgłosiłeś się późno, rób co chcesz. Dla mnie ten parser to było w sumie 100 linijek kodu i 10-20 minut pracy (obsługa komentarzy, apostrofów, słów kluczowych i numerów [hexów też]). Nie mniej jest to najprostszy sposób na prosty i dobry parser kodu, skoro chciałeś rozwiązania to masz.

Ponad to nie wiem jakby zareagowała prowadząca zajęcia na taki skomplikowany kod, gdyż w gruncie rzeczy mieliśmy na razie same podstawy Pascala.

Bo przecież programowanie obiektowe to coś tak odjechanego że nikt normalny tego nie zastosuje. Już nie mówiąc że ten kod można dosyć łatwo przerobić bez obiektówki.

Nie myślę o Twojej pomocy jako o jakimś towarze, tylko jako o pomocy doświadczonego kolegi.

Możesz to traktować jak towar, mam to gdzieś. Póki ten towar się nie zmarnuje i nie zostanie odrzucony w stylu 'nie użyje bo mi się nie chce' to nie ma problemu. Natomiast nie lubię gdy ktoś daje pseudopowody nieużycia tego kodu bo mu się nie chce ogarnąć jakiejś bardziej skomplikowanej rzeczy i liczy na to że ludzie będą mu szukać rozwiązania pisanego na miarę. Nie mam zamiaru ci dalej pomagać, this statement is final.

1 użytkowników online, w tym zalogowanych: 0, gości: 1