Exemple de
|
"In fiecare zi se invata ceva nou."
SOLON
In prezentul capitol vom ilustra mecanismele de definire, fixare si utilizare a extinderilor la nivel formal, apoi citeva exemple practice de extinderi.
Pentru definirea extinderilor ( de date, de operatii, de instructiuni si de dirijari ), se folosesc mijloace metalingvistice ( terminali metalingvistici ) care se vor combina cu elementele lingvistice deja existente.
Declararea extinderilor are, in principiu, aceeasi forma ca si definirea clasica a oricarui element intr-un limbaj de programare comun, dar ea se bazeaza pe folosirea unor metaterminali speciali.
Fiecare compartiment de definire a unui element ( de reamintit ca trebuiesc mentionate: pragmatica, sintaxa, semantica, contextul utilizarii si exemplele de utilizare ale noului element introdus in limbaj ) este compus din sub-elemente de definire care la rindul lor formeaza un metalimbaj. Astfel, vom avea un metalimbaj de definire a pragmaticii, un metalimbaj de definire a sintaxei si asa mai departe.
Vom introduce tipul de data matrice de tip real pe care il vom defini prin intermediul elementelor deja existente in limbajul de programare pe care dorim sa-l extindem. Astfel, presupunem deja definite: tipul real, neterminalii <ident>, constantele intregi, delimitatorii metalingvistici _DBL_ ( Data Begin Layout ), _DCO_ ( Data COntext ), _DSY_ ( Data SYntax ), _DSE_ ( Data SEmantics ), _DEX_ ( Data EXample ), _DEL_ ( Data End Layout ), _AS_.
|
In acest prim caz, se observa ca s-a extins limbajul PASCAL, prin definirea unui nou tip de data: matrice cu elemente reale.
Fiecare tip are asociata o multime de operatori. Utilizind tipul de data matrice definit mai sus, vom ilustra aici definirea operatiei de sumare a doua matrici reale. Presupunem cunoscute: operatia de adunare a doi reali, instructiunile de asignare, de ciclare, functiile care furnizeaza numarul de linii, respectiv coloane ale unei matrici, metaterminalii _OBL_ ( Operation Begin Layout ), _OCO_ ( Operation COntext ), _OSY_ ( Operation SYntax ), _OSE_ ( Operation SEmantics ), _OEX_ ( Operation EXample ), _OEL_ ( Operation End Layout ).
Consideram ca matricile sint declarate si au aceleasi dimensiuni.
Vom suprascrie ( defini ) operatorul + pentru a suporta sumarea de matrici.
|
Vom defini o instructiune grafica de desenare a unui triunghi,
cunoscindu-se coordonatele virfurilor. In limbaj sint deja implementate
instructiunile PutPixel
, LineTo
. Nu lipsesc delimitatorii metalingvistici:
_SBL_ ( Statement Begin Layout ), _SCO_ ( Statement COntext ),
_SSY_ ( Statement SYntax ), _SSE_ ( Statement SEmantics ),
_SX_ ( Statement eXample ), _SEL_ ( Statement End Layout
).
Vom construi o instructiune grafica pentru desenarea unui triunghi cunoscindu-se coordonatele virfurilor.
|
Limbajul extensibil va dispune de urmatoarele constructii implementate: <statement>, <for>, expresiille aritmetice, variabile de ciclu de tip intreg, metaterminalii _CBL_ ( Control Begin Layout ), _CCO_ ( Control COntext ), _CSY_ ( Control SYntax ), _CSE_ ( Control SEmantics ), _CEX_ ( Control EXample ), _CEL_ ( Control End Layout ).
Putem defini un nou ciclu, pe baza ciclului For
deja
existent in limbaj.
|
Observatie: Dupa cum s-a vazut mai sus, definirea unui element implica imbogatirea limbajului cu noi constructii ( apar astfel noi terminali si neterminali, plus noi reguli ale gramaticii asociate limbajului respectiv ).
Sub ORACLE in implementarea SQL-PLUS, utilizind pre-compilatorul PRO-C:
#define <stdio.h>
#define <strings.h>
#define <SQL.h>
main()
{
....
EXEC SQL BEGIN DECLARE SECTION; /* inceputul sectiunii de declaratii SQL*/
VARCHAR uid[20];
VARCHAR pwd[20];
VARCHAR lid[1];
VARCHAR e_id[1];
VARCHAR nmar[4];
VARCHAR nouv[500][5];
VARCHAR ldesign[120];
EXEC SQL END DECLARE SECTION;
printf("\nLogin:"); /* inceput interogare */
gets(uid.arr);
uid.len=strlen(uid.arr);
uid.arr[uid.len]='\0';
printf("\nPassword:");
gets(pwd.arr);
pwd.len=strlen(pwd.arr);
pwd.arr[pwd.len]='\0';
EXEC SQL WHENEVER SQLERROR GOTO err;
EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;
printf("\nConnection to ORACLE...done\n");
EXEC SQL WHENEVER NOT FOUND CONTINUE;
/* exemplu de cursor explicit */
EXEC SQL DECLARE CURSOR FOR \
SELECT L_DESIGN FROM LOT \
WHERE L_ID=:lid;
EXEC SQL OPEN c1;
EXEC SQL FETCH c1 INTO :ldesign;
EXEC SQL CLOSE c1;
/* exemplu de cursor implicit */
EXEC SQL SELECT DISTINCT substr(M.OAED_ID,1,5) \
INTO :nouv FROM OAED M \
WHERE M.LOC_ID LIKE :edif_id || :nmar || \
'%' AND M.OAED_ID LIKE :lid || '%' ;
....
err:
printf("\nIncorrect login!\n");
return 1;
....
}
Relatiile sint in mod natural definite ca facind parte dintr-un record in PASCAL, utilizind o extindere de tip: RELATION care e o implementare a unei tabele SQL:
TYPE DATE=string[8]; { ZZ-LL-AA }
TYPE TStud=RECORD { cimpurile bazei de date }
name:string[60];
number:integer;
points:integer;
born_date:DATE;
END;
TYPE RStud=RELATION OF TStud;
VAR stud:RStud;
....
DEFINE MACRO COMPLEX_MATRIX (M,N)
WHERE MACROARGS M,N
TO BE ARRAY[1..M,1..N,1..2] OF REAL
END MACRO
VAR X:COMPLEX_MATRIX(3,4);
Dupa expandare, in codul sursa va apare:
VAR X:ARRAY[1..3,1..4,1..2] OF REAL; /*macro COMPLEX_MATRIX*/
Definirea unei noi dirijari ( control ):
SMACRO for s1(VARIABLE:INTEGER) = s2(EXPRESSION:INTEGER)
CASE 1: while s3(EXPRESSION:LOGICAL)
CASE 2: by s4(EXPRESSION:INTEGER) OPTIONALLY
CASE 3: to s5(EXPRESSION:INTEGER)
do s6(STATEMENT)
LET BE
LABEL l1,l2
l1 LET s1=s2
l2 IF (1 :: s3) THEN
s6 : GO TO l1
(3 :: s1<=s5) THEN
s6
LET s1=s1 + (2 :: s4) (NOT 2 :: 1)
GO TO l2
END IF
END SMACRO
Apelarea macro-ului:
for i=1 while i<=6 do INPUT a(i)
REM label_??? sint generate de preprocesorul extensibil
label_1 LET i=1
label_2 IF i<=6 THEN
INPUT a(i) : GO TO label_1
END IF
for i=1 to 10 do PRINT i*i
label_3 LET i=1
label_4 IF i<=10 THEN
PRINT i*i
LET i=i+1
END IF
Max (A,B:single_type) = ( if A > B then A else B )
#define Max(A,B) (A) > (B) ? (A) : (B)
Let ++ be a left associative unary operator as
succ(_:ANY_TYPE) with precedence > '+'