Twoje PC  
Zarejestruj się na Twoje PC
TwojePC.pl | PC | Komputery, nowe technologie, recenzje, testy
B O A R D
   » Board
 » Zadaj pytanie
 » Archiwum
 » Szukaj
 » Stylizacja

 
M E N U
  0
 » Nowości
0
 » Archiwum
0
 » Recenzje / Testy
0
 » Board
0
 » Rejestracja
0
0
 
Szukaj @ TwojePC
 

w Newsach i na Boardzie
 
OBECNI NA TPC
 
 » GULIwer 01:13
 » Shark20 01:08
 » elliot_pl 01:06
 » Pinokio.p 01:03
 » ham_solo 00:53
 » Paweł27 00:51
 » Martens 00:45
 » Wedrowiec 00:33
 » slanter 00:17
 » Mademan 00:17
 » Holyboy 00:16
 » piszczyk 00:13
 » resmedia 23:54
 » Tomasz 23:53
 » yanix 23:48
 » g5mark 23:42
 » homzik 23:32
 » DJopek 23:29
 » Lukas12p 23:23
 » stefan_nu 23:21

 Dzisiaj przeczytano
 41122 postów,
 wczoraj 25974

 Szybkie ładowanie
 jest:
włączone.

 
ccc
TwojePC.pl © 2001 - 2024
A R C H I W A L N A   W I A D O M O Ś Ć
    

[RegEx] - usuwanie komentarzy i literałów z kodu źródłowego - jak? , bwana 6/01/12 11:50
Co chcę uzyskać: mam kod źródłowy deklaracji pakietu PL/SQL (budową przypomina deklarację klasy). Chcę w sposób znormalizowany zebrać informacje o procedurach i funkcjach pakietu (w przypadku klasy byłyby to deklaracje metod) oraz o parametrach wywołania tych procedur i funkcji.

Występują dwa rodzaje komentarzy:

tekst kodu -- tekst komentarza

tekst kodu /* tekst
komentarza */ dalszy ciąg kodu

Mogą też w różnych miejscach występować literały tekstowe w pojedynczych albo w podwójnych cudzysłowach. Literał tekstowy może przełamywać linię tekstu bez dodatkowego znacznika.

No i teraz - chcę pozbyć się i komentarzy i literałów tekstowych. Ale nie bardzo już wiem, jak uwzględnić to, że w treści komentarza mogą wystąpić cudzysłowy i na odwrót - w literałach tekstowych mogą wystąpić znaki komentarzy '--' lub '/* */'.

przykładowo:
-----------------------------------------------------------------
package nazwa

/*
pakiet zawiera procedurę proc_a do której należy
podać parametr otoczony znakami apostrofu czyli '

*/

procedure proc_a(a varchar2 default 'ala ma
kota /*');
procedure proc_b(b varchar2 default 'ale
ma kota*/');
procedure proc_c(c varchar2 default 'ale ma -- problem');

end;
-----------------------------------------------------------------
jak widać, trudno jest określić sposób wyrzucania literałów i komentarzy z kodu. No ale przecież edytory tekstu radzą sobie z tym i może znacie jakieś spostrzeżenie, które naprowadzi mnie na rozwiązanie problemu.

Nie chodzi mi o gotowe narzędzie, tylko o algorytm, ponieważ całość chcę umieścić w pakiecie PL/SQL, który ma kod innych pakietów prezentować w znormalizowanej postaci (krótko mówiąc ma generować szablony wywołań dowolnie wskazanego API).

Rozwiązanie sprowadza się do określenia sposobu stwierdzenia, że "w tym miejscu w kodzie jest wnętrze komentarza" i "w tym miejscu w kodzie jest wnętrze literału tekstowego". Pomożecie?

Próbuję to rozwiązać używając wyrażeń regularnych i jestem daleki od implementowania automatu skończonego ze stosem, którym faktycznie coś takiego da się w miarę łatwo opanować - tylko że trzeba napisać sam automat:-D Tak więc - raczej sposobami "inżynierskimi" sypnijcie.

"you don't need your smile when I cut
your throat"

  1. próbowałeś , Holyboy 6/01/12 12:19
    wyszukać i zastąpić te znaki komentarzy znajdujące się wewnątrz stringów ?

    Strength is irrelevant.
    Resistance is futile.
    We wish to improve ourselves.

    1. jasne:-D , bwana 6/01/12 12:58
      tylko trzeba umieć rozpoznać, czy początek/koniec stringa jest w kodzie, czy w komentarzu. Podobnie na odwrót - trzeba rozpoznać, czy początek/koniec komentarza jest w literale tekstowym czy w kodzie.

      Dlatego jednak robię to czytając kolejno po jednym znaku i podejmując decyzje i zapamiętując stany:
      - czy to znak rozpoczynający/kończący komentarz
      - czy to znak rozpoczynający/kończący literał tekstowy
      czyli jednak zrobiłem coś w stylu DAS-a. No ale działa.

      kod wygląda tak (o ile to kogoś interesuje, PL/SQL jako język programowania ogólnego zastosowania to jak za króla Ćwieczka):

      PROCEDURE strip_comments(p_code IN out nocopy CLOB) AS
      l_position NUMBER:=1;
      in_dash_comment boolean:=FALSE;
      in_mline_comment boolean:=FALSE;
      in_s_literal boolean:=FALSE;
      in_d_literal boolean:=FALSE;

      l_result CLOB;
      l_len NUMBER:=LENGTH(p_code);

      FUNCTION in_comment RETURN boolean AS
      BEGIN
      return in_dash_comment or in_mline_comment;
      END;

      FUNCTION in_literal RETURN boolean AS
      BEGIN
      return in_s_literal or in_d_literal;
      end;

      BEGIN
      loop
      IF substr(p_code,l_position,2) = '--' and not in_mline_comment and not in_literal THEN
      in_dash_comment:=TRUE;
      l_position:=l_position+2;
      ELSIF substr(p_code,l_position,2) = '/*' AND NOT in_dash_comment and not in_literal THEN
      in_mline_comment:=TRUE;
      l_position:=l_position+2;
      elsif substr(p_code,l_position,1) = chr(10) AND in_dash_comment THEN
      in_dash_comment:=FALSE;
      l_result:=l_result||chr(10);
      l_position:=l_position+1;
      elsif substr(p_code,l_position,2) = '*/' AND in_mline_comment THEN
      in_mline_comment:=FALSE;
      l_position:=l_position+2;
      elsif substr(p_code,l_position,1) = '''' AND NOT in_s_literal and not in_comment THEN
      in_s_literal:=TRUE;
      l_position:=l_position+1;
      elsif substr(p_code,l_position,1) = '''' AND in_s_literal and not in_comment THEN
      IF substr(p_code,l_position+1,1) = '''' THEN
      l_position:=l_position+2;
      ELSE
      in_s_literal:=FALSE;
      l_position:=l_position+1;
      end if;
      END IF;
      IF NOT in_comment and not in_literal THEN
      l_result:=l_result||substr(p_code,l_position, 1);
      end if;
      l_position:=l_position+1;
      exit when l_position>=l_len;
      END loop;
      dbms_output.put_line(l_result);
      p_code:=l_result;
      end;

      "you don't need your smile when I cut
      your throat"

  2. A może coś z tego: , Tig3r 6/01/12 19:42
    http://www.perlmonks.org/...s%20from%20a%20file%3F

  3. A dokładniej , Tig3r 6/01/12 19:53
    /\*[^*]*\*+([^/*][^*]*\*+)*/|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|\n+|--[^\n]*|.[^/"--'\\]*)

    Drobna zmiana żeby jeszcze złapać te komentarze w stylu --
    To wyrażenie powinno podzielić tekst na kawałki. Sprawdzenie czym jest dany kawałek nie powinno być już problemem :D

    BTW do testowania i pisania wyrażeń regularnych "na żywo" polecam RegEx Coach - świetny i darmowy.

    1. na pierwszy rzut oka może być OK - o ile takie krzaczki na pierwszy rzut oka można ocenić , bwana 6/01/12 22:39
      ale wydaje mi się, że to powinno być wyrażenie z modyfikatorem non-greedy.

      Niestety, składnia PL/SQL jest nieco inna niż Perlowa (chyba najbardziej znana) i nad takim gotowcem i tak trzeba popracować.

      "you don't need your smile when I cut
      your throat"

    
All rights reserved ® Copyright and Design 2001-2024, TwojePC.PL