Sunteți pe pagina 1din 43

TEMA 7 – EXTINSE == ASIGGNMENT 1

 Se cere analizorul sintactic pentru urmatoarea gramatica:

Fisier= fisier (linie | epsilon)

Linie=(ID (lista_param | epsilon) | epsilon) NL

Lista_param = param (, lista_param | epsilon)

Param=( ID | F) (param | epsilon)

Struct atom {
string nume;
int categorie; // categorie lexicala
int cod;
}a;
atom *a;
// fisier=fisier (linie | epsilon)
//
// apare recursivitatea de stanga => introducem un neterminal nou si rescriem gramatica
// fisier=fisier (linie | epsilon) devine
//
// fisier = (linie | epsilon) fisierprim
// fisierprim = fisierprim | epsilon
int fisier(){
if(linie()){
a=a->next;
if(fisierprim()){
a=a->next;
return 1;
}else{
printf("Fisierprim invalid");
exit(0);
}
elseif(!linie()){
printf("Linie incorecta");
exit(0);
}
else{
if(fisierprim()){
a=a->next;
return 1;
}
} //pentru linie | epsilon
}
2
int fisier(){
if(linie()){
a=a->next;
if(fisierprim()){
a=a->next;
return 1;
}elseif(!linie()){
printf("Fisierprim invalid");
exit(0);
}
a=a->next;
return 1; //pentru epsilon
}
int fisierprim(){
if(fisierprim()){
a=a->next;
return 1;
}
elseif(!fisierprim())
printf("Fisierprim invalid");
exit(0);
else{
a=a->next;
return 1; //pentru epsilon
}
}
// linie=(ID (lista_param | epsilon) | epsilon) NL
int linie(){
if(strcmp(a->categorie, "ID") == 0){
a=a->next;
if(lista_param()){
a=a->next;
if(strcmp((a->nume), "NL")==0){
a=a->next;
return 1;
}
}elseif(!lista_param()){
printf("Lista de parametri incorecta");
exit(0);
}elseif(strcmp((a->nume), "NL")==0){
a=a->next;
return 1;
} //pentru lista_param | epsilon
}elseif(strcmp(a->categorie, "ID") != 0){
printf("ID incorect");
exit(0);
}elseif(strcmp((a->nume), "NL")==0){
a=a->next;
return 1;
} //pentru lista_param | epsilon //pentru ID | epsilon
}
3
// lista_param=param (, lista_param | epsilon)
int lista_param(){
if(param()){
a=a->next;
if(strcmp(a->nume, ",") == 0){
a=a->next;
return 1;
}
elseif(strcmp(a->nume, ",") != 0)
printf("Lipseste ,");
exit(0);
else{
a=a->next;
return 1; //pentru , lista_param | epsilon
}
}else{
printf("Eroare la parametru!");
exit(0);
}
}
// param=(ID | F) (param | epsilon)
int param(){
if((strcmp(a->categorie, "ID") == 0) || (strcmp(a->categorie, "F") == 0)){
a=a->next;
if(param()){
a=a->next;
return 1;
}
elseif(param()!=1){
printf("Parametru incorect\n");
exit(0);
}
else{
a=a->next;
return 1; //pentru (param | epsilon)
}else{
printf("ID sau F lipsa\n");
exit(0);
}
}

ASSIGNMENT 2
Se cere automatul cu stari finite si analizorul lexical care recunoaste un
numar intreg, scris in oricare dintre cele 3 baze de numeratie: binar, zecimal,
hexazecimal. Partile subliniate reprezinta atomi lexicali

BD=0 | 1
DD=0 .. 9
HD=0 .. 9 | a .. f | A .. F
INT= 0 (x HD+ | b BD+) | DD+

#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
struct atom
{
char nume;
int codLexical;//2=identificator,1=constanta,0=eroare, nu avem cuvinte cheie
};

int stare=0;
atom BD(char c)
{
atom b;
if ((c=='0')||(c=='1'))
{
b.codLexical=1;
b.nume=c;
}
else
{
b.codLexical=0;
b.nume=c;
stare=-1;
};
return (b);
};
atom DD(char c)
{
atom b;
if (isdigit(c))
{
b.codLexical=1;
b.nume=c;
}
else
{
b.codLexical=0;
b.nume=c;
stare=-1;
};
return (b);
};

atom HD(char c)
{
atom b;
if (isdigit(c))
{
b.codLexical=1;
b.nume=c;
}
else
{
if ((isupper(c))&&(c<='F'))
{
b.codLexical=1;
b.nume=c;
}
else
{
if ((islower(c))&&(c<='f'))
{
b.codLexical=1;
b.nume=c;
}
else
{
b.codLexical=0;
b.nume=c;
stare=-1;
}
}
};
return (b);
};

atom INT(char c)
{
atom b;
if (stare==0)
{
if (isdigit(c))
{
if(c=='0') //starea 2, 0
{
b.codLexical=1;
b.nume=c;
stare=2;
}
else //starea 1, numar>0
{
b.codLexical=1;
b.nume=c;
stare=1;
}
}
else //eroare, asteptam un numar
{
b.codLexical=0;
b.nume=c;
stare=-1;
}
return b;
}
else
{
if (stare==1)
{
return (DD(c));
}
else
{
if(stare==2)
{
if (c=='x')
{
b.codLexical=1;
b.nume=c;
stare=3;
}
else
{
if (c=='b')
{
b.codLexical=1;
b.nume=c;
stare=5;
}
else stare=-1;
}
return b;
}
if (stare==3)
{
return(HD(c));
}
if (stare==5)
{
return(BD(c));
}
}
}
};

void afisare(atom Atom[],int lungime)


{
int i;
cout<< "Afisarea atomilor:\n";
cout<<"Sirul de nume :";
for(i=0; i<lungime; i++)
{
cout<< Atom[i].nume<<"| ";
};
cout<<"\nCodurile lexicale:";
for(i=0; i<lungime; i++)
{
cout<< Atom[i].codLexical<<"| ";
};
cout<<"\n";
};
int main()
{
atom atomul[9999];
int i,nr;
string intrarea;
intrarea="xxxxxxxx";
nr=0;
stare=0;
cout<<"Sirul "<<intrarea;
for (int i = 0; i < intrarea.size(); i++)
{
atomul[nr]=INT((char)intrarea[i]);
if (((int)atomul[nr].codLexical==0)||(stare==-1))
{
i=intrarea.size();
cout<<"Contine erori:";
};
nr++;
};
cout<<"\n";
afisare(atomul, nr);
intrarea="0b10101";
nr=0;
stare=0;
cout<<"Sirul "<<intrarea;
for (int i = 0; i < intrarea.size(); i++)
{
atomul[nr]=INT((char)intrarea[i]);
if (((int)atomul[nr].codLexical==0)||(stare==-1))
{
i=intrarea.size();
cout<<"Contine erori:";
};
nr++;
};
cout<<"\n";
afisare(atomul, nr);
intrarea="0xfFaA510101";
nr=0;
stare=0;
cout<<"Sirul "<<intrarea;
for (int i = 0; i < intrarea.size(); i++)
{
atomul[nr]=INT((char)intrarea[i]);
if (((int)atomul[nr].codLexical==0)||(stare==-1))
{
i=intrarea.size();
cout<<"Contine erori:";
};
nr++;
};
cout<<"\n";
afisare(atomul, nr);
intrarea="353450431";
nr=0;
stare=0;
cout<<"Sirul "<<intrarea;
for (int i = 0; i < intrarea.size(); i++)
{
atomul[nr]=INT((char)intrarea[i]);
if (((int)atomul[nr].codLexical==0)||(stare==-1))
{
i=intrarea.size();
cout<<"Contine erori:";
};
nr++;
};
cout<<"\n";
afisare(atomul, nr);
return 0;
}
TEMA 8 – EXTINSA == ASSIGNMENT 3
Sa se scrie un analizor sintactic corespunzator gramaticii de mai jos:

<declaratii>::=<declaratie>|<declaratii> ; <declaratie>
<declaratie>::= ID (<stars>|epsilon) ID ([INT] | ( <args>|epsilon) )
<stars>::=STAR|STAR <stars>
<args>::=<arg>|<arg> , <args>
<arg>::= ID (<stars>|epsilon) ID
 
Observatii: ID, INT si STAR sunt atomi lexicali. Toate celelalte caractere care sunt
ingrosate reprezinta de asemenea atomi lexicali. Analizorul lexical pentru aceasta
gramatica se considera deja implementat.

În cazul <declaratii>::=<declaratie>|<declaratii> ; <declaratie> se observă o


recursivitate la stânga imediată ce trebuie eliminată pentru a putea realiza o analiză
sintactică descendentă.
Această transformare se realizează prin introducerea unui neterminal nou și prin
mărirea numărului producțiilor:
<declaratii>::=<declaratie> <declaratii_prim>
<declaratii_prim>::= epsilon| ; <declaratie> <declaratii_prim>
Astfel se obține următorul analizor sintactic:
enum CODURI_LEXICALE { NEDEF, ID, INT, STAR, VIRGULA, PVIRGULA,
PSTANGA, PDREAPTA };

CODURI_LEXICALE ultim; //ultimul cod lexical citit

void init_lex(void); //initializeaza analizorul lexical

void lex(void); //citeste un nou cod lexical

void eroare(int cod); //semnaleaza o eroare

void declaratii(void);

void declaratii_prim(void);

void declaratie(void);

void stars(void);

void args(void);

void arg(void);

int main()

init_lex();

lex();

declaratii();

void declaratii(void)

{
declaratie();

declaratii_prim();

void declaratii_prim(void)

if (ultim == PVIRGULA)

lex();

declaratie();

declaratii_prim();

void declaratie(void)

if (ultim != ID)

eroare(1); //se astepta la ID

return;

lex();

if (ultim != PSTANGA)

eroare(2); //se astepta la (

return;

lex();

if (ultim != PDREAPTA)

stars();
}

if (ultim != PDREAPTA)

eroare(3); //se astepta la )

return;

lex();

if (ultim != ID)

eroare(1); //se astepta la ID

return;

lex();

if (ultim != PSTANGA)

eroare(2); //se astepta la (

return;

lex();

if (ultim == PDREAPTA)

lex();

return;

if (ultim == INT)

else

{
if (ultim != PSTANGA)

eroare(2); //se astepta la (

return;

lex();

if (ultim != PDREAPTA)

args();

if (ultim != PDREAPTA)

eroare(3); //se astepta la )

return;

lex();

if (ultim != PDREAPTA)

eroare(3); //se astepta la )

return;

void stars(void)

if (ultim != STAR)

eroare(4); //se astepta la STAR

return;
}

lex();

if (ultim == STAR)

stars();

void args(void)

arg();

if (ultim == VIRGULA)

args();

void arg(void)

if (ultim != ID)

eroare(1); //se astepta la ID

return;

lex();

if (ultim != PSTANGA)

eroare(2); //se astepta la (

return;

lex();
if (ultim != PDREAPTA)

stars();

if (ultim != PDREAPTA)

eroare(3); //se astepta la )

return;

lex();

if (ultim != ID)

eroare(1); //se astepta la ID return;

lex();
}

TEMA 9 – EXTINSA == ASSIGNMENT 4


Se cere să se scrie un analizor sintactic pentru gramatica de mai jos.
 
 
·    <source_file> ::= <declarations> <code>
·    <declarations> ::= vars <list_of_variables> ;
·    <list_of_variables> ::= <variable> | <list_of_variables> , <variable>
·    <code> ::= <statements> .
·    <statements> ::= <assignment> | <statements> ; <assignment>
·    <assignment> ::= <variable> := <expression>
·    <expression> ::= <expression> + <term> | <expression> - <term> | <term>
·    <term> ::= <term> * <factor> | <term> / <factor> | <factor>
·    <factor> ::= <number> | <variable>

Rezolvare:

Daca se considera gramatica complet definita atunci terminalele sunt cele scrise cu bold.
In cazul in care gramatica nu este complet definita atunci <number> si <variable> sunt
neterminale.
Programul analizorului sintactic este:

Atom a; //structura care continue atomii dfiniti de analizorul lexical

int source_file()
{
if(declarations())
{
a = getNextAtom();
if(code())
{
return 1;
}
else error "Lipseste codul";
}
else error "Lipsesc declaratiile";
}

int declarations()
{
if(strcmp(a->name, "vars"))
{
a = getNextAtom();
if(list_of_varibles())
{
a = getNextAtom();
if(strcmp(a->name, ";"))
{
return 1;
}
else error "Lipseste ;";
}
else error "Lipseste lista de variabile";
}
else error "Lipseste vars";
}

int list_of_variables()
{
if(strcmp(a->category, “variable”))
{
return 1; // s-a considerat interpretarea (<variable>) | (<list_of_variables> ,
<variable>)
}
else if (list_of_variables())
{
a = getNextAtom();
if (strcmp(a->name, ","))
{
a = getNextAtom();
if (a->category, “variable”)
{
return 1 ;
}
else error "Lipseste variabila";
}
else error "Lipseste ,";
}
else error "Lipseste variabila sau lista de_variabile";
}
}

int code ()
{
if(statements ())
{
a=getNextAtom();
if(strcmp(a->name, "."))
{
return 1;
}
else error "Lipseste .";
}
else error "Lipseste code ";
}

int statements()
{
if((assignment())
{
return 1; // s-a considerat interpretarea (<assignment>) | (<statements> ;
<assignment>)
}
else if (statements())
{
a = getNextAtom();
if (strcmp(a->name, ";"))
{
a = getNextAtom();
if(assignment())
{
return 1;
}
else error "Lipseste assignment";
}
else error "Lipseste ;";
}
else error "lipseste assignment sau statements";
}

int assignement()
{
if (strcmp(a->category, “variable”))
{
a = getNextAtom();
if (strcmp(a->name, ":"))
{
a = getNextAtom();
if (strcmp(a->name, "="))
{
a = getNextAtom();
if (expression())
{
return 1;
}
else error "Lipseste expression";
}
else error "Lipseste =";
}
else error "Lipseste :";
}
else error "Lipseste variable";
}

int expression()
{
if (expression())
{
a = getNextAtom();
if ((strcmp(a->name, "+")) || (strcmp(a->name, "-")))
{
a = getNextAtom();
if (term())
{
return 1;
}
else error "Lipseste term";
}
else error "Lipseste + sau -";
}
else
{
if(term())
{
return 1 ;
}
else error "Lipseste term sau expression";
}
}

int term()
{
if (term())
{
a = getNextAtom();
if ((strcmp(a->name, "*")) || (strcmp(a->name, "/")))
{
a = getNextAtom();
if (factor())
{
return 1;
}
else error " Lipseste factor";
}
else error "Lipseste * sau /";
}
else
{
if(factor())
{
return 1 ;
}
else error "Lipseste factor sau term";
}
}

int factor()
{
if(strcmp(a->category, “number"))
{
return 1;
}
else
{
if (strcmp(a->category, “variable”))
{
return 1 ;
}
else error "Lipseste number sau variable";
}
}

In cazul in care <number> si <variable> sunt neterminale acesteaea se pot evalua similar pana la
cifra si litera.
ASSIGNMENT 5
Sa se scrie un analizor lexical corespunzator setului de atomi din definitia de mai
jos. Se va realiza si automatul cu stari finite aferent acestei definitii.

 escape -> \ (0|n|t|”|’|r)
 string -> “(char | escape)* ”
 char -> a..z|A..Z|0..9|_|spatiu

Automatul cu stări finite aferent definiției din enunț:

Codul Analizorului lexical:

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

typedef struct _Token{


char *buf;
struct _Token *next;
} Token;

int printError(const char *format, ...)


{
va_list va;
va_start(va,format);
fprintf(stderr,"parse error: ");
vfprintf(stderr,format,va);
fputc('\n',stderr);
va_end(va);
exit(1);
}

Token* tokenize(char *buf)


{
Token *root = NULL;
Token *tok = NULL;
Token *tmp = NULL;
int state = 0;
int sp = 0;
int ep = 0;
int dif = 0;

while (1){
if (buf[ep] == '\0'){
break;
}
switch (state) {
case 0:
if (buf[sp] != '"'){
sp++;
ep++;
} else
{ ep++;
state = 1;
}
break;
case 1:
if ( buf[ep] == '\\' ){
ep++;
state = 2;
}else if (('a' <= buf[ep] && buf[ep] <= 'z') ||
('A' <= buf[ep] && buf[ep] <= 'Z') ||
('0' <= buf[ep] && buf[ep] <= '9') ||
buf[ep] == '_' ||
buf[ep] == ' ') {
ep++;
}else if ( buf[ep] == '"' ){
ep++;
state = 4;
}else {
state = 3;
}
break;
case 2:
if (buf[ep] == '0' ||
buf[ep] == 'r' ||
buf[ep] == 'n' ||
buf[ep] == 't' ||
buf[ep] == '\'' ||
buf[ep] == '"'){
ep++;
state = 1;
} else { state =
3;
}
break;
case 3:
printError("sir: %s \n positie %d", buf, ep);
break;
case 4:
tmp = (Token *) malloc(sizeof(Token));
dif = ep - sp;
tmp->buf = (char*)malloc(dif + 1 );
memcpy(tmp->buf, buf+sp, dif); tmp-
>buf[dif] = '\0'; tmp->next = NULL;
if (!root
root = tmp;
}else
tok->next = tmp;
}
tok = tmp;
sp = ep;
state = 0;
break;
default:
break;
}
}
return root;
}

void printTokens(Token *root)


{
printf("Tokeni lexicali: \n");
while (root){
printf("%s\n", root->buf);
root = root->next;
}
}

int main(int argc, const char * argv[])


{
char unparsedBuff[50] = "\"primul token\"
ajkd \"doi\"\"al_trei\\nlea\"\"\"";

Token *parsedTokens;
parsedTokens = tokenize(unparsedBuff);
printTokens(parsedTokens);
return 0;
}

ASSIGNMENT 6
Se cere analizorul sintactic pentru a citi un fisier de balante de plati in care pe
fiecare linie se afla optional oricare dintre cele trei elemente, in ordinea data:
 
a)      cod (atom lexical ID, sir de caractere si cifre care incep cu un caracter) urmat
optional de oricate subcoduri, despartite prin “->”
b)      incasare (atom lexical F, un numar real)
c)       plata (atom lexical F, un numar real), obligatoriu precedat de “#” daca e doar
un numar pe linie, altfel “#” este optional
 
Pot exista si linii complet vide, iar separatorul de linii este atomul lexical NL. Intre
elemente se pune “,”. Fisierul poate fi complet gol. Toate partile subliniate sunt
considerate atomi lexicali.
 
Gramatica:

fisier=linie (fisier | epsilon) | epsilon


linie= ( cod (, (F (, op | epsilon) | # F) | epsilon) | F (, op | epsilon) | # F | epsilon )
NL
cod=cod -> ID | ID
op=(# | epsilon) F

Rezolvare:

cod=cod -> ID | ID
Se observa o recursivitate la stânga imediată, care trebuie eliminată, dupa metoda:
A→Aα⏐β ⇒ A→βA’
A’→αA’⏐ε
Vom introduce un neterminal nou, mărind numărul producțiilor:
cod = ID cod_prim
cod_prim= ->ID cod_prim | epsilon

Vom obține următorul analizator sintactic:

Linie – desfașurat după definitie


Linie – simplificat

PROGRAMUL:
//......................
enum ATOMI_LEXICALI {ID, NL, DIEZ, VIRGULA, SAGEATA, ALTUL};
void eroare(int error_code); // pentru raportarea erorilor
void fisier(void); //prelucreaza un fisier
void linie(void); // prelucreaza o linie
void cod(void); //prelucreaza un cod
void cod_prim(void); //v. mai sus – eliminarea recursivitatii la stanga
void op(void); // prelucreaza o plata
void citeste_atom(void); // citeste un atom lexical (joaca rol de ALEX)
ATOMI_LEXICALI atom_lexical; //tipul de atom lexical citit
int avem_erori=0; //aici tinem evidenta daca avem erori sau nu

int main()
{
citeste_atom(); //citeste un nou atom lexical
fisier(); //prelucrează fișierul
if (avem_erori==0)
printf ("Programul este corect dpdv. sintactic");
return 0;
}
void fisier()
{
if (atom_lexical) //daca fisierul nu este gol
{
linie(); // prelucram linia
citeste_atom();
fisier();
}
} //end fisier

void linie()
{
if (atom_lexical ==NL) //daca e linie vida
return;
if (atom_lexical == ID) //daca avem cod (atom lexical ID)
{
cod(); //prelucreaza codul
citeste_atom(); //cautam o virgula sau un NL dupa cod
if (atom_lexical) //daca se citeste ceva
{
if (atom_lexical ==NL) //daca linia se termina dupa cod
return;
if (atom_lexical !=VIRGULA) //daca se citeste ceva care nu e virgula
{
eroare(4); // ar trebui sa urmeze o virgula
return;
}
citeste_atom(); // Daca am ajuns aici, s-a citit o virgula. Citim atomul de dupa
virgula.
if ((atom_lexical !=F) && (atom_lexical != DIEZ))
{
eroare(5); // dupa virgula trebuie sa urmeze F sau DIEZ
return;
}
}
}

if (atom_lexical == F) //daca avem o incasare (fie după virgulă, fie prima pe linie daca nu există
cod)
{
citeste_atom();
if (atom_lexical) //daca se citeste ceva
{
if (atom_lexical==NL) //daca linia se termina dupa incasare
return;
if (atom_lexical !=VIRGULA) //daca se citeste ceva care nu e virgula
{
eroare(4); // ar trebui sa urmeze o virgula
return;
}
op(); // dacă am ajuns aici fără erori, atunci după virgulă ar trebui să urmeze o
plată, pe care o prelucrăm cu funcția op()
citeste_atom();
if ((atom_lexical) && (atom_lexical !=NL))
// daca mai există ceva in fisier după plată, ar trebui să urmeze pe o linie nouă
{
eroare(2); // se asteapta NL sau end of file după plată( deoarece e finalul
liniei)
return;
}
}

else if (atom_lexical == DIEZ) // F si #F nu pot coexista pe aceeași linie, deci #F e pe


ramura de else if si se ajunge la el doar daca nu am avut direct F dupa virgula
{
citeste_atom(); //aici ar trebui sa se citeasca un nr real
if(atom_lexical != F)
{
eroare(3); //se așteaptă nr. real după diez
return;
}
citeste_atom();
if ((atom_lexical) && (atom_lexical !=NL))
//daca mai exista ceva in fisier, ar trebui să urmeze pe o linie nouă
{
eroare(2); // ar trebui sa fie NL sau end of file la finalul unei linii
return;
}
}
} //end linie

void cod()
{
if (atom_lexical != ID)
{
eroare(1); // trebuia sa urmeze un ID
return;
}
citeste_atom(); //dacă nu există erori, trecem mai departe la atomul următor
cod_prim();
}

void cod_prim()
{
if (atom_lexical==SAGEATA)
{
citeste_atom();
if (atom_lexical != ID)
{
eroare(1); // Ar trebui sa urmeze un ID
return;
}
cod_prim(); //pot urma mai multe sub-coduri introduse prin săgeată, deci
continuăm să le căutăm după fiecare săgeată
}
}

void op()
{
citeste_atom();
if (atom_lexical == DIEZ) // daca incepe cu un diez, trecem la atomul urmator
citeste_atom();
if(atom_lexical != F) //ar trebui să urmeze un nr. real. Aici ajungem indiferent daca există
diez sau nu.
eroare(6); //plata ar trebui sa fie un nr real – dacă nu este, semnalăm eroarea
}

void eroare(int error_code); // pentru raportarea erorilor


{
avem_erori=1; //daca s-a ajuns aici, avem erori si punem variabila globala pe 1
switch (error_code) { //acestea sunt tipurile de erori pe care le-am putea intalni
case 1:
printf ("Ar trebui sa urmeze un ID: sir de caractere si cifre care incep cu un
caracter.");
GRIZLI777
break;
case 2:
printf ("Ar trebui sa urmeze un NL la finalul liniei sau sa fie end of file.");
break;
case 3:
printf ("Ar trebui sa urmeze un nr real dupa DIEZ.");
break;
case 4:
printf ("Ar trebui sa urmeze o virgula.");
break;
case 5:
printf ("Dupa virgula ar trebui sa urmeze F sau DIEZ.");
break;
case 6:
printf ("Plata ar trebui sa fie un nr real.");
break;
}
}

TEMA 6 – EXTINSA == ASSIGNMENT 7


Cerinte:

Realizati un analizor sintactic pentru urmatoarea gramatica

<lista_ramuri> = <ramura>|<lista_ramuri> <ramura>


<ramura> = <lista_val> : <instr> ;
<lista_val> = <constanta> , <lista_val>|<constanta>
<constanta> = <constanta_num>|<constanta_car>
<constanta_car> = litera
<const_num> = <nr_intreg>|<nr_real>
<nr_intreg> = <nrBaza10>|<baza>@ cifra

Raspuns:
Deoarece in cazul: <lista_ramuri> =  <ramura>|<lista_ramuri> <ramura>, exista recursivitate la
stanga, aceasta trebuie eliminata prin introducerea unui neterminal nou:

<lista_ramuri> =  <ramura> <lista_ramuri_prim>


<lista_ramuri_prim> = epsilon| ; <ramura> <lista_ramuri_prim>

void error(int error_code); /* raporteaza eroare */


void lista_ramuri(void);
void lista_ramuri_prim(void);
void ramura(void);
void lista_val(void);
void constanta(void);
void constanta_car(void);
void const_num(void);
void nr_intreg(void);

void get_next_lex(void); /* citeste urmatorul element lexical */


COD_LEXICAL codLex; /* elementul lexical citit */
int main()
{
get_next_lex();
lista_ramuri();
return 0;
}

void lista_ramuri()
{
ramura();
lista_ramuri_prim();
}

void ramura()
{
lista_val();

get_next_lex();
if( codLex != ':' )
{
error(1); /* se astepta " : " */
return;
}

get_next_lex();
instr(); /* verifica daca e instructiune */

get_next_lex();
if( codLex != ';')
{
error(2); /* se astepta " ; " */
return;
}
}

void lista_ramuri_prim()
{
get_next_lex();

ramura();
lista_ramuri_prim();
}

void lista_val()
{
get_next_lex();
constanta();

get_next_lex();
if(codLex != ',')
{
error(3); /* se astepta " , " */
return;
}

lista_val();
}
void constanta()
{
const_num();
constanta_car();
}
void const_num()
{
nr_intreg();
nr_real();
}
void constanta_car
{
get_next_lex();

if(((codLex <= 'a') || (codLex >= 'z') ) && ((codLex <= 'A') || (codLex >= 'Z')))
{
error(4); /* se astepta un caracter */
return;
}
}
void nr_intreg()
{
get_next_lex();

if((codLex < 0)||(codLex > 9))


{
error(5); /* se astepta un numar */
return;
}
}

Analizorul sintactic obtinut:


Tema la LTFC
Se da: D=0..9
Se da: F=[+ | -] D+ [. D+] [(e | E) [+ | -] D+]

Se cere: Automatul cu stari finite si analizorul lexical care recunoaste un numar zecimal, care
poate fi dat si in formatul cu mantisa si exponent.

2. Codul aferent analizatorului lexical


Analizorul lexical reprezinta interfata dintre programul sursa si compilator. El realizeaza
parcurgerea textului de intrare, caracter cu caracter, grupand aceste caractere în unitati logice
numite atomi. 
Clasele de atomi intalnite in majoritatea limbajelor de programare sunt: identificatori, cuvinte
cheie, constante numerice (intregi, reale, eventual reprezentate în diferite baze de numeratie),
operatori (aritmetici, logici, relationali), semne de punctuatie, delimitatori, constante de tip
caracter, respectiv sir de caractere, comentarii.
Forma generala a unui atom este:
Struct Atom {

string nume atom;

int categorie_lexicala;
int cod;

} a;

Sa dat: D=0..9
Sa dat: F=[+ | -] D+ [. D+] [(e | E) [+ | -] D+]

a) String atom *a;

1. int op1(){ // echivalentul lui [+|-] din functia de mai sus


b)Categorie lexicala si cod

if (a Strcmp(a categorie_lexicala, “[“)==0) {

a= getNextAtom();

if(strcmp(a-categorie_lexicala,”+” || “|” || “-“)==0{

a= getNextAtom();

if (Strcmp(a-categorie_lexicala, “]“)==0) {

a= getNextAtom();

return 1;

else {

printf ("Eroare la delimitatori!");

return 1;

else {

printf ("Eroare la operatori!");

return 1;

else {

printf ("Eroare la op1!");

Sa dat: F=[+ | -] D+ [. D+] [(e | E) [+ | -] D+]


2. int D1(){ //Numit D in ecuatia de mai sus//

cifra=0;

while(cifra>=0&&D1<=9){

a= getNextAtom();

printf ("Cifrele atomului D1 sunt de la 0 la 9")

a++;

}
return 1;

Sa dat: F= [+ | -] D+ [. D+] [(e | E) [+ | -] D+]

3. Int op2(){ //Operator numit + in ecuatia de mai sus//

if(strcmp(a-categorie_lexicala,”+”)==0{

a= getNextAtom();

return 1;

else {

printf ("Eroare la operator +");

Sa dat: F= [+ | -] D+ [. D+] [(e | E) [+ | -] D+]


4. Int delimitator1(){ //Numit mai sus [.D]//

Cifra_forma_fractie=0;

if (a -Strcmp(a-categorie_lexicala, “[“)==0) {

a= getNextAtom();

while(Cifra_forma_fractie >=0&&D1<=9){

a= getNextAtom();

if(strcmp(a-categorie_lexicala,”+”)==0{

a= getNextAtom();

if (a -Strcmp(a-categorie_lexicala, “]“)==0) {

a= getNextAtom();

return 1;

else {

printf ("Eroare la delimitatorul ]");

return 1;

else {

printf ("Eroare la operator +");

printf ("Cifrele atomului D2 sunt de la 0 la 9")

a++;

return 1;
}

return 1;

else {

printf ("Eroare la delimitator1!");

Sa dat: F= [+ | -] D+ [. D+] [(e | E) [+ | -] D+]


5. Int nr_zecima_exponent() { //Adica [(e|E)[+|-] din ecuatia de mai sus

D=0;

while(D >=0&&D<=9){

a= getNextAtom();

if (while(D >=0&&D<=9){ //de aici incolo abordam D+] din ecuatia data//

a= getNextAtom();

if(strcmp(a-categorie_lexicala,”+”)==0{

a= getNextAtom();

if (Strcmp(a-categorie_lexicala, “]“)==0) {

a= getNextAtom();

return 1;

else {

printf ("Eroare la delimitatori!");

return 1;

else {

printf ("Eroare la operator +");

return 1;

else {

printf (“Cifrele nu sunt intre 0 si 9 ]");

printf ("Cifrele atomului zecimal sunt de la 0 la 9")

a++;

return 1;

}
1. Sa se scrie analizorul sintactic pentru urmatoarea gramatica:
 
propozitii: propozitii propozitie
propozitie: ( subiectSimplu ARE | subiectCompus AU ) numar .
subiectSimplu: ID
subiectCompus: ID (, subiectCompus | epsilon)
numar: INT LEI ( SI INT BANI | epsilon ) | INT BANI
 
 

2. Sa se scrie analizorul lexical care valideaza persoane cu nume


corespunzatoare urmatorului format:
PERSOANA: NUME SPATIU PRENUME
NUME: LITERA_MARE LITERA_MICA+
PRENUME: LITERA_MARE LITERA_MICA+ ( ( MINUS LITERA_MARE LITERA_MICA+ ) | epsilon )
 

3. Sa se scrie analizorul sintactic pentru urmatoarea gramatica:


 
clasa: CLASS ID {   listaDecl   }
decl: declVar | declFunc
listaDecl: listaDecl decl | epsilon
declVar: ID ID
declFunc: ID ID ( argumente )
argumente: declVar ( , argumente | epsilon ) | epsilon

4. Sa se realizeze analizorul lexical pentru gramatica de mai jos:

LITERA ::= a..z | A..Z


DIGIT ::= 0..9
ID ::= LITERA ( LITERA | DIGIT )*
REAL ::= DIGIT+ [ . DIGIT+ ]

5. Sa se realizeze analizorul sintactic pentru gramatica de mai jos. Analizorul


lexical se considera cunoscut. Componentele scrise ingrosat sunct considerati
atomi lexicali.
tesut: celule fibre| tesut
celule: (celula)+
celula: ADN ARN

Enunt problema
Se cere să se scrie un analizor sintactic pentru gramatica de mai jos.

•<text> ::= <sentences> <endword>


•<sentences> ::= <sentences> <sentence> | <sentence>
•<sentence> ::= <noun_phrase> <verb_phrase> <punctuator>
•<noun_phrase> ::= <noun_phrase> <conjunction> <noun_phrase_item> | <noun_phrase_item>
•<noun_phrase_item> ::= <article> <genitive> <noun> | <article> <noun> | <genitive> <noun>
•<verb_phrase> ::= <verb> <noun_phrase>

Analizorul lexical pentru aceasta gramatica se presupene deja implementat.


Avem doua cazuri de recursivitate la stanga pe care am eliminat-o prin introducerea unui terminal nou

<sentences> ::= <sentences> <sentence> | <sentence>


<sentences> ::= <sentence> <sentences_prim>
<sentences_prim> ::=epsilon|;<sentences_prim> <sentence>

<noun_phrase> ::= <noun_phrase> <conjunction> <noun_phrase_item> | <noun_phrase_item>


<noun_phrase> ::= <noun_phrase_item><noun_phrase_prim>
<noun_phrase_prim> ::=epsilon|;<noun_phrase_item><noun_phrase_prim>

Gramatica devine:
<text> ::= <sentences> <endword>
<sentences> ::= <sentence> <sentences_prim>
<sentences_prim> ::=epsilon|;<sentences_prim> <sentence>
<sentence> ::= <noun_phrase> <verb_phrase> <punctuator>
<noun_phrase> ::= <noun_phrase_item><noun_phrase_prim>
<noun_phrase_prim> ::=epsilon|;<noun_phrase_item><noun_phrase_prim>
<noun_phrase_item> ::= <article> <genitive> <noun> | <article> <noun> | <genitive> <noun>
<verb_phrase> ::= <verb> <noun_phrase>

CODURI_LEXICALE last; //ultimul cod lexical citit


void init_lex(void); //initializeaza analizorul lexical
void get_next_lex(void); //citeste un nou cod lexical
void erorr(int cod_erorr); //semnaleaza o eroare

void text(void);
void sentences(void);
void sentences_prim(void);
void sentence(void);
void noun_phrase(void);
void noun_phrase_prim(void);
void noun_phrase_item(void);
void verb_phrase(void);

int main() {
init_lex();
get_next_lex();
text();
}

//<text> ::= <sentences> <endword>

void text(void){
senteces();
enword();
}
//<sentences> ::= <sentence> <sentences_prim>

void sentences(void) {
sentence();
sentences_prim();
}
//<sentences_prim> ::=epsilon|;<sentences_prim> <sentence>

void sentences_prim(void){
if (last == “;”)
{ get_next_lex();
sentences_prim();
sentence();
}
}

//<sentence> ::= <noun_phrase> <verb_phrase> <punctuator>

void sentence(void){
noun_phrase();
verb_phrase();
punctuator();
}

//<noun_phrase> ::= <noun_phrase_item><noun_phrase_prim>

void noun_phrase(void){
noun_phrase_item();
noun_phrase_prim();
}

//<noun_phrase_prim> ::=epsilon|;<noun_phrase_item><noun_phrase_prim>

void noun_phrase_prim(void){
if (last ==”;”)
{get_next_lex();
noun_phrase_item();
noun_phrase_prim();
}
}

//<noun_phrase_item> ::= <article> <genitive> <noun> | <article> <noun> | <genitive> <noun>


void noun_phrase_item(void){
if(last==article)
{
get_next_lex();

if (last==genitive){
noun();
}
else if {
return 0;
}
}
else{
noun();
}
}

//<verb_phrase> ::= <verb> <noun_phrase>

void verb_phrase(void){
verb();
noun_phrase();
}

S-ar putea să vă placă și