Professional Documents
Culture Documents
Ex LFTC Final
Ex LFTC Final
Ex LFTC Final
5. Sa se realizeze analizorul sintactic pentru gramatica de mai jos. Analizorul lexical se considera
cunoscut. Componentele scrise ingrosat sunct considerati atomi lexicali.
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();
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);
}
}
<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
Observații: ID, INT si STAR sunt atomi lexicali. Toate celelalte caractere care sunt îngroșate reprezintă de
asemenea atomi lexicali. Analizorul lexical pentru această gramatică se consideră deja implementat.
Struct Atom {
string nume;
int categorie_lexicala;
int cod;
} a;
Atom *a;
//c.<stars>::=STAR|STAR <stars>
// ambiguitate: <stars> ::= STAR <starsp>
// <starsp>::= <stars> | epsilon
//<stars> ::= STAR <starsp>
int stars()
{
if (stracmp(a->nume, "STAR") == 0)
{
if (starsp(a))
{
a = getNextAtom();
return 1;
}
else {
printf("Eroare <starsp>");
exit (0);
}
}
else {
printf("Eroare STAR");
exit (0);
}
}
//<starsp>::= <stars> | epsilon
int starsp()
{
if (stars(a))
{
a = getNextAtom();
return 1;
}
else {
printf ("Eroare <stars>");
exit(0);
}
return 1; //epsilon
}
//e.<arg>::= ID (<stars>|epsilon) ID
int arg()
{
if (strcmp(a->nume, "ID") == 0)
{
a = getNextAtom();
if (stars(a))
{
a = getNextAtom();
if (strcmp(a.nume, "ID") == 0)
{
a = getNextAtom();
return 1;
}
else {
printf("Lipseste ID dupa <stars>");
exit(0);
}
}
else if (strcmp(a->nume, "ID") == 0)
{
a = getNextAtom();
return 1;
}
else {
printf("Lipseste al doilea ID");
exit(0);
}
}
else {
printf("Lipseste primul ID");
exit(0);
}
}
9. Se cere să se scrie un analizor sintactic pentru gramatica de mai jos.
(Assignment 4)
Atom a;
int source_file()
{
if(declarations())
{
a = getNextAtom();
if(code())
{
return 1;
}
else error "Missing code";
}
else error "Missing declarations";
}
int declarations()
{
if(strcmp(a->name, "vars"))
{
a = getNextAtom();
if(list_of_varibles())
{
a = getNextAtom();
if(strcmp(a->name, ";"))
2
{
return 1;
}
else error "Missing token ;";
}
else error "Missing list of variables";
}
else error "Missing keyword/terminal 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 "Missing variable";
}
else error "Missing token ,";
}
else error "Missing variable or list_of_variables";
}
}
int code ()
{
if(statements ())
{
a=getNextAtom();
if(strcmp(a->name, "."))
{
return 1;
}
else error "Missing token .";
}
else error "Missing code/empty code";
}
int statements()
{
if((assignment())
{
3
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 "Missing assignment";
}
else error "Missing token ;";
}
else error "Missing assignment or 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 "Missing expression";
}
else error "Missing token =";
}
else error "Missing token :";
}
else error "Missing variable";
}
int expression()
{
if (expression())
{
a = getNextAtom();
if ((strcmp(a->name, "+")) || (strcmp(a->name, "-")))
{
a = getNextAtom();
if (term())
4
{
return 1;
}
else error " Missing term";
}
else error "Missing token + or -";
}
else
{
if(term())
{
return 1 ;
}
else error "Missing term or expression";
}
}
int term()
{
if (term())
{
a = getNextAtom();
if ((strcmp(a->name, "*")) || (strcmp(a->name, "/")))
{
a = getNextAtom();
if (factor())
{
return 1;
}
else error " Missing factor";
}
else error "Missing token * or /";
}
else
{
if(factor())
{
return 1 ;
}
else error "Missing factor or term";
}
}
int factor()
{
if(strcmp(a->category, “number"))
{
return 1;
}
else
{
if (strcmp(a->category, “variable”))
5
{
return 1 ;
}
else error "Missing number or variable";
}
(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
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
}
11. 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+
AD
2 AD 3
Altc
X eva
4
Start 0 0 1 BD
a
B cev
Alt
5 BD 6
DD va
ltce
A
7
#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
};
//pt. simplitate, stochez atomul ca vector, deci atributul va fi indexul.
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)
{
1/9
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;
}
}
}; 2/9
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
{
//cel putin primul caracter ce defineste starea a fost ales.
if (stare==1)
{
return (DD(c));
}
else
{
if(stare==2)
{
if (c=='x')
3/9
{
//starea 3
b.codLexical=1;
b.nume=c;
stare=3;
}
else
{
if (c=='b')
{
//starea 5
b.codLexical=1;
b.nume=c;
stare=5;
}
else stare=-1; //avem o eroare...
}
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++)
{
4/9
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;
}
Ce este un compilator?
Un compilator este un translator care citeşte un program scris într-un limbaj de nivel înalt (limbajul
sursă) şi îl traduce într-un limbaj echivalent în alt limbaj, de nivel mai scăzut (limbajul obiect sau
destinaţie).
escape -> \ (0|n|t|”|’|r)
string -> “(char | escape)* ”
char -> a..z|A..Z|0..9|_|spatiu
Rezolvare:
#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)
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] == '_' ||
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:
case 4:
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;