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
|