Documente Academic
Documente Profesional
Documente Cultură
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));
}
}
}
};
<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.
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)
return;
lex();
if (ultim != PSTANGA)
return;
lex();
if (ultim != PDREAPTA)
stars();
}
if (ultim != PDREAPTA)
return;
lex();
if (ultim != ID)
return;
lex();
if (ultim != PSTANGA)
return;
lex();
if (ultim == PDREAPTA)
lex();
return;
if (ultim == INT)
else
{
if (ultim != PSTANGA)
return;
lex();
if (ultim != PDREAPTA)
args();
if (ultim != PDREAPTA)
return;
lex();
if (ultim != PDREAPTA)
return;
void stars(void)
if (ultim != STAR)
return;
}
lex();
if (ultim == STAR)
stars();
void args(void)
arg();
if (ultim == VIRGULA)
args();
void arg(void)
if (ultim != ID)
return;
lex();
if (ultim != PSTANGA)
return;
lex();
if (ultim != PDREAPTA)
stars();
if (ultim != PDREAPTA)
return;
lex();
if (ultim != ID)
lex();
}
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:
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
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
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;
}
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:
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
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;
}
}
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
}
Raspuns:
Deoarece in cazul: <lista_ramuri> = <ramura>|<lista_ramuri> <ramura>, exista recursivitate la
stanga, aceasta trebuie eliminata prin introducerea unui neterminal nou:
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();
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.
int categorie_lexicala;
int cod;
} a;
Sa dat: D=0..9
Sa dat: F=[+ | -] D+ [. D+] [(e | E) [+ | -] D+]
a= getNextAtom();
a= getNextAtom();
if (Strcmp(a-categorie_lexicala, “]“)==0) {
a= getNextAtom();
return 1;
else {
return 1;
else {
return 1;
else {
cifra=0;
while(cifra>=0&&D1<=9){
a= getNextAtom();
a++;
}
return 1;
if(strcmp(a-categorie_lexicala,”+”)==0{
a= getNextAtom();
return 1;
else {
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 {
return 1;
else {
a++;
return 1;
}
return 1;
else {
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 {
return 1;
else {
return 1;
else {
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
Enunt problema
Se cere să se scrie un analizor sintactic pentru gramatica de mai jos.
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>
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();
}
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();
}
}
void sentence(void){
noun_phrase();
verb_phrase();
punctuator();
}
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();
}
}
if (last==genitive){
noun();
}
else if {
return 0;
}
}
else{
noun();
}
}
void verb_phrase(void){
verb();
noun_phrase();
}