2.63        PROFAN2

PROFAN² è un linguaggio nato in Germania nel 1992 dove ha avuto una buona diffusione (oltre 15000 copie vendute). In inglese esiste la versione 3.3; la versione 8 è del 2004.

Il linguaggio ha punti di somiglianza con il Basic, quali la gestione dinamica delle stringhe, i suffissi dei nomi che individuano il tipo di dato ed alcune funzioni. Le istruzioni di input output derivano dal PASCAL. A differenza del Basic è obbligatorio dichiarare le variabili utilizzate.

E’ un linguaggio senza operatori aritmetici o di confronto, che sono sostituiti da funzioni.

Le strutture complesse sono le liste e, dalla versione 6 gli array, fino a tre dimensioni. Esistono 4 liste, una per ogni tipo di variabile, ad esse si accede per indice.

L’assegnazione di un valore ad una variabile ha la struttura LET variabile = espressione, con LET obbligatorio, ciò è difforme dall’assegnazione di un valore ad un membro di una lista:

Declare alfa$

DIM$ 80 ' lista di stringhe

LIST$ 1 = "PROFAN"

...

LET alfa$ = @LIST$(1)

I commenti sono individuati da REM ad inizio riga o da ' in qualsiasi punto, non è possibile mettere più di una istruzione per riga.

La struttura di controllo completa è:

IF espressione     ' la valutazione di espressione deve fornire 0 o 1

Istruzione/i

ELSEIF espressione ' ELSEIF può mancare

Istruzione/i

ELSE espressione ' ELSE può mancare

Istruzione/i

ENDIF

Ma è anche disponibile l’assegnazione condizionale: LET variabile = @If(espressione,N2,N3) e l’istruzione analoga ad IF espressione THEN istruzione, che in PROFAN² ha la forma CASE espressione : istruzione.

La gestione delle iterazione avviene tramite While espressione ... EndWhile e WhileNot espressione ... EndWhile, al posto di EndWhile è accettato anche Wend. Non esiste l’equivalente del FOR ... NEXT.

Per le funzioni e le subroutine dell’utilizzatore è disponibile il GOSUB, la macrodefinizione DEF e la definizione di subroutine: PROC nomeprocedura. In questa si possono dichiarare variabili locali ed accedere alle variabili con cui nomeprocedura è richiamata, introducendo queste tramite la dichiarazione PARAMETERS var1, .... L’istruzione RETURN permette di restituire un valore, che è accessibile tramite funzione, ad esempio una stringa sarà ottenuta con @$(0).

Ci sono istruzioni per interagire con il sistema operativo, e l’hardware, la gestione della grafica, dei dispositivi multimediali, il supporto SQL e dei data base in formato dBASE. Inoltre è gestita in modo semplice ed efficace la programmazione delle interfacce grafiche.

PROFAN² è disponibile su diverse piattaforme, permette un facile sviluppo interattivo e la produzione di un eseguibile in p-code.

Qui di seguito il listato di un programma, con interfaccia grafica, per il controllo di espressioni regolari .  

' PROFAN 3.3 e 7

Declare tPattern%,tDecode%,cmFine%,cmControlla%, nStack%

' estrae un numero da stato

DEF @EstrNum(2) @VAL(@Substr$(@LIST$(@ADD(190,@%(1))),@%(2),","))

' estrae un stringa da stato

DEF @EstrChr(2) @Substr$(@LIST$(@ADD(190,@%(1))),@%(2),",")

 

PROC push

  PARAMETERS n%,chars$

  INC nStack%

  LIST$ nStack% = @ADD$(@Str$(n%),@ADD$(",",chars$))

ENDPROC

 

PROC Consuma

  PARAMETERS Stringa$, crt$

  While @GT(@InStr(@MID$(Stringa$,1,1),crt$),0)

    LET Stringa$ = @MID$(Stringa$, 2,200)

  Wend

  Return Stringa$

ENDPROC

 

PROC CercaStato

      PARAMETERS Stato%, Crt$

      Declare i%, Tipo$, xxx%, Flag%

        LET flag% = 0

        LET i% = 0

        WHILE @EQU(flag%,0)

          LET xxx% = @EstrNum(i%,1) ' estrae Stato attuale

        IF @EQU(xxx%,-1)

            LET Flag% = -1              ' non trovato

        Elseif @EQU(xxx%,Stato%)

            LET Tipo$ = @EstrChr(i%,2)   ' tipo carattere

            If @EQU$(Tipo$,"q")            ' quantificatore

               case @GT(@InStr(crt$,"*+?"),0) : LET Flag% = I%

            Else

             ' carattere uguale o . (match con tutto)

               CASE @EQU$(Crt$,Tipo$) : LET Flag% = I%

               CASE @EQU$(".",Tipo$) : LET Flag% = I%

            EndIf

          EndIf

          INC i%

      WEND

        RETURN Flag%

ENDPROC

 

PROC Verifica

      PARAMETERS Stringa$

      Declare Risultato%,A$,ptrn$,ncrt%,J%

      Let Risultato% = 1                          ' vero

      Let J% = 1                            ' segue stack verifica

        WhileNot @GT(J%,nStack%)

        LET ptrn$ = @SUBSTR$(@LIST$(J%),2,",")

          LET ncrt% = @VAL(@SUBSTR$(@LIST$(J%),1,","))

          IF @EQU(ncrt%,-1)

             Consuma Stringa$, ptrn$

             LET Stringa$ = @$(0)  ' consumati i caratteri

          Elseif @AND(@EQU(ncrt%,0),@GT(@LEN(Stringa$),0))

             CASE @GT(@INSTR(@MID$(Stringa$,1,1),ptrn$),0) : LET Stringa$ = @MID$(Stringa$,2,200)

          Elseif @EQU(ncrt%,1)

             If @GT(@INSTR(@MID$(Stringa$,1,1),ptrn$),0)

            LET Stringa$ = @MID$(Stringa$,2,200)

           else

            LET Risultato% = 0

             EndIf

          EndIf

          INC J%

      wend

      CASE @GT(@LEN(Stringa$),0) : LET Risultato% = 0

        RETURN Risultato%

ENDPROC

 

PROC Controlla

      Declare n%, Stato%, Pattern$,Decode$,ptr%,ptrn$, Ris$

        Declare I%, A$,Tipo$

        LET nStack% = 0

      LET Pattern$ = @GetText$(tPattern%)

        LET Decode$ = @GetText$(tdecode%)

      Print "Pattern: ";Pattern$,"Stringa: ";Decode$

      LET Stato% = 0                                   ' 0 stato iniziale

        LET i% = 0

      WHILE  @LT(i%,@LEN(Pattern$))

        INC i%

        LET A$ = @Mid$(Pattern$, i%, 1)

        CercaStato stato%, A$

          LET ptr% = @%(0)                          ' valore di ritorno

        If @EQU(ptr%, -1)                           ' -1 carattere illegale

          Print Pattern$, "  Carattere illegale"

          Print @MID$("                             ",1,@SUB(I%,1));"^"

          RETURN "Errore!"

        EndIf

        LET stato% = @EstrNum(ptr%,3)

          LET Tipo$ = @MID$(@EstrChr(ptr%,4),1,1)

          CASE @EQU$("c",Tipo$) : push  1, A$             ' 1 carattere

        if @EQU$("q",Tipo$)

              LET ptrn$ = @substr$(@LIST$(nStack%),2,",") ' pop

              DEC nStack%                            ' prelevo da stack

            CASE @EQU$(A$,"*") : push -1, ptrn$         ' - 1 illimitato

            If @EQU$(A$,"+")

            push  1, ptrn$

              push  -1, ptrn$                           ' - 1

            Else

                CASE @EQU$(A$,"?") : push 0, ptrn$        ' 0 1 o nessuno

            EndIf

           endIf

         CASE @EQU$("d",Tipo$) : push 1, "0123456789"

      WEND

      Verifica decode$

        LET Ris$ = @ADD$(Decode$, @IF(@%(0)," corretta"," errata"))

      @MessageBox(Ris$,"Risultato",0)

ENDPROC

 

PROC Finestra

        Declare E%,D%

      Let D% = @CreateDialog(%HWnd,"PROFAN - Espressioni Regolari",130,90,360,290)

        @CreateText(D%,"Pattern:",         10, 15, 50,20)

        @CreateText(D%,"Stringa da riconoscere:",    10, 40, 200,20)

      Let tPattern% = @CreateEdit(D%,"-?\d*.?\d+",          220, 15,100,25)

      Let tDecode%  = @CreateEdit(D%,"-123.14",          220, 40,100,25)

        Let cmControlla% = @CreateButton(D%,"&Controlla",180,210, 70,30)

      Let cmFine%      = @CreateButton(D%,"&Fine",   250,210, 70,30)

      @SetFocus(tPattern%)

      Let E% = 0

      WhileNot E% ' loop eventi

          WaitInput

          CASE @Equ(%Key,13) :  Controlla "" ' ENTER tasto default

        CASE @GetFocus(cmControlla%) : Controlla

        CASE @GetFocus(cmFine%) : Let E% = 1

      Wend

      @DestroyWindow(D%)

  ENDPROC

 

'   PROGRAMMA PRINCIPALE

'-------------

      Dim$ 200 ' array per riconoscitore stringhe

                 ' nella forma n,caratteri accettati, es. -1,0123456789  (digit)

                 ' n = 1: un carattere, 0 = 0 o 1 carattere, -1 illimitati

      ' Automa a stati finiti per interpretare espressione regolare in array da 190 in su

      ' I stato attuale, II  carattere in esame ( o tipo), III stato successivo

      ' IV  azione: e escape, c carattere, q quantificatore, d cifre

      List$ 190 = "0,\,2,escape"

      List$ 191 = "0,.,1,carattere"

      List$ 192 = "1,q,3,quantificatore"

      List$ 193 = "1,\,2,escape"

      List$ 194 = "1,.,1,carattere"

      List$ 195 = "2,d,1,digit"

      List$ 196 = "2,q,1,quantificatore"

      List$ 197 = "3,\,2,escape"

      List$ 198 = "3,.,1,carattere"

      List$ 199 = "-1"

      Finestra "" ' richiama creazione finestra

      End