Sunteți pe pagina 1din 13

Universidad Nacional de San Agustin

Compiladores

Informe del compilador

Aparicio Tony , Salomon Gabriel


Escalante Calcina, Judith

30 de diciembre de 2016
Informe del compilador

Índice
1. Análisis léxico 2
1.1. Clase scanner.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2. Función getStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2. Análisis sintáctico 4
2.1. Clase parser.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.1. Gramática completa . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.2. Tablas generadas con el Anagra . . . . . . . . . . . . . . . . . 7
2.1.3. Función analize . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3. Análisis semántico 10
3.1. Tabla de simbolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

4. Conclusiones 12

5. Referencias 12

1
Informe del compilador

1. Análisis léxico

1.1. Clase scanner.h


# ifndef SCANNER_H
# define SCANNER_H
# include < vector >
# include < iostream >
# include < unordered_map >
# include < fstream >
using namespace std ;

class Scanner
{
public :
Scanner ( string fileName ) ;
vector < string > getBuffer () ;
void initStaticTable () ;
void getStreamFromFile ( string fileName ) ;
void getStream ( string input ) ;
private :
unordered_map < int , unordered_map < char , int > > table ;
unordered_map < int , unordered_map < char , int > >
advance ;
unordered_map < int , bool > finalStates ;
unordered_map < int , string > typeStates ;
vector < string > buffer ;
unordered_map < string , string > static_table ;
int init_state ;
};
# endif // SCANNER_H

Explicación: En la clase Scanner recibe el nombre de la tabla que representa a


nuestro autómata, tiene como datos miembro estructuras unordered map table, que
contiene el autómata, finalStates que contiene un mapeo de los estados de acep-
tación,typeStates que contiene información para identificar que tipo de token se
acepta; un vector buffer para almacenar los tokens resultantes, una tabla estática
para almacenar e identificar sı́mbolos especiales y un entero initState que almacena
el estado inicial del autómata.

2
Informe del compilador

1.2. Función getStream


void Scanner :: getStream ( string input , SymbolTable & t )
{
string :: iterator it = input . begin () ;
string token = " " ;

int tmp_state , state = init_state ;


unordered_map < string , string >:: iterator table_it ;
int line =1;
Token * tmp ;

while ( it != input . end () )


{
while (! finalStates [ state ])
{
tmp_state = table [ state ][* it ];
if (* it == ’\ n ’)
line ++;
if (! advance [ state ][* it ])
{
token +=* it ;
it ++;
}
state = tmp_state ;
}
if ( typeStates [ state ]!= " whitespace " &&
typeStates [ state ]!= " mult_comment " &&
typeStates [ state ]!= " single_comment " )
{
table_it = static_table . find ( token ) ;
if ( table_it != static_table . end () )
{

tmp = new Token ( static_table [ token


] , line ) ;
buffer . push_back ( tmp ) ;
}

else
{

3
Informe del compilador

tmp = new Token ( typeStates [ state ] ,


line ) ;
buffer . push_back ( tmp ) ;
t . insert_symTab ( token , p ) ;

}
}
token = " " ;
state = init_state ;
}
// Token tmp (" $", line );
tmp = new Token ( " $ " , line ) ;
buffer . push_back ( tmp ) ;
}

Explicación: La función getStream que recibe la cadena que se va a procesar y la


tabla de sı́mbolos para almacenar la información correspondiente a los identificadores
detectados, la entrada se lee caracter a caracter y se va llenando el buffer con los
tokens correspondientes.

2. Análisis sintáctico

2.1. Clase parser.h


# ifndef PARSER_H
# define PARSER_H

# include < vector >


# include < stack >
# include < iostream >
# include < unordered_map >
using namespace std ;

class Production {
public :
string leftSide ;
vector < string > rightSide ;
Production ( string l )

4
Informe del compilador

{
leftSide = l ;
}
void insertSymbol ( string s )
{
rightSide . push_back ( s ) ;
}
void printProduction ()
{
cout < < leftSide < < " : " ;
for ( size_t i = 0; i < rightSide . size () ; i ++) {
cout < < rightSide [ i ] < < " " ;
}
cout < < endl ;
}
};

class Action {
public :
int type ;
int number ;
Action ( int t , int n ) : type ( t ) , number ( n ) {};
};

class Parser
{
public :
Parser () ;
void initGrammar () ;
void initActionTable () ;
void initGotoTable () ;
void analyze ( vector < string > buffer ) ;
private :
unordered_map < int , unordered_map < string , Action > >
actionTable ;
unordered_map < int , unordered_map < string , int > >
gotoTable ;
unordered_map < int , Production > grammar ;
stack < int > parsingStack ;
};

5
Informe del compilador

# endif // PARSER_H

Explicación: Para la fase análisis sintático se define una clase Production para alma-
cenar las distintas producciones de la gramática a procesar, una clase Acción para
identificar los tipos de acciones(shift,reduce,accept) y finalmente la clase Parser que
contiene dos estructuras unordered-map para almacenar las tablas Action y Goto,
una estructura para almacenar la gramática completa y una pila para realizar el
proceso de reconocimiento de cadenas.

2.1.1. Gramática completa

S : FUN_DEC S | STAT S | ;
FUN_DEC : DATA_TYPE id left_par ARG_LIST right_par BLOCK ;
ARG_LIST : ARG COMMA_LIST | ;
ARG : DATA_TYPE id ;
COMMA_LIST : comma ARG COMMA_LIST | ;
DATA_TYPE : int_type | double_type | void_type |
float_type | long_type | bool_type | color_type |
char_type | byte_type | str_type ;
BLOCK : left_curly BODY right_curly ;
BODY : LOOP BODY | SELECTION BODY | STAT BODY | ;
LOOP : FOR_STAT | WHILE_STAT ;
FOR_STAT : for left_par INIT semicolon EXP semicolon EXP
right_par FOR_BODY ;
INIT : int_type assign_op EXP ;
FOR_BODY : STAT | BLOCK ;
WHILE_STAT : while left_par EXP right_par BLOCK ;
STAT : DEC | F_CALL2 | OBJ_ST ;
F_CALL2 : F_CALL1 semicolon ;
F_CALL1 : id left_par PARAM_LIST right_par ;
PARAM_LIST : EXP COMMA_LIST | ;
COMMA_LIST : comma EXP COMMA_LIST | ;
EXP : EXP OPER SIDE | SIDE | OBJ_EXP ;
SIDE : DATA | left_par EXP right_par ;
OPER : add_op | min_op | mult_op | assign_op | div_op |
mod_op | equal_op | nequal_op | lt_op | gt_op | lte_op
| gte_op | and_op | or_op | not_op | inc_op | dec_op
| add_assign | minus_assign | mult_assign | div_assign
;

6
Informe del compilador

DATA : int_lit | double_lit | char_lit | oct_lit |


hex_lit | str_lit | id ;
DEC : DATA_TYPE id B semicolon | id assign_op EXP
semicolon ;
B : assign_op EXP | ;
OBJ_ST : OBJ_EXP semicolon ;
OBJ_EXP : id O ;
O : dot P Q ;
Q : dot P Q | ;
P : id | F_CALL1 ;
SELECTION : IF_STAT | SWITCH_STAT ;
IF_STAT : if left_par EXP right_par IF_BODY ELSE_OPT ;
IF_BODY : BLOCK | STAT ;
ELSE_OPT : else ELSE_BODY | ;
ELSE_BODY : BLOCK | STAT | IF_STAT ;
SWITCH_STAT : switch left_par EXP right_par left_curly
SWITCH_BODY right_curly ;
SWITCH_BODY : CASE_STAT SWITCH_BODY | DEFAULT | ;
CASE_STAT : case EXP colon CASE_BODY B_OPT ;
CASE_BODY : semicolon | STAT D ;
D : STAT D | ;
B_OPT : break semicolon | ;
DEFAULT : default colon CASE_BODY B_OPT ;

2.1.2. Tablas generadas con el Anagra

Tablas generadas con el Anagra.

7
Informe del compilador

Figura 1: a) Tabla acción y b) Tabla ir a

2.1.3. Función analize

string Parser :: analyze ( vector < Token > buffer )


{
size_t i =0;
bool error = false ;
string process = " " ;
parsingStack . push (0) ;

while (! error && i < buffer . size () )


{
auto top = parsingStack . top () ;
auto actionIt = actionTable [ top ]. find ( buffer [ i ].
content ) ;

if ( actionIt != actionTable [ top ]. end () )


{
if ( actionIt - > second . type ==2) // Shift
operation
{

8
Informe del compilador

parsingStack . push ( actionIt - > second . number


);
i ++;
}
else if ( actionIt - > second . type ==1) // Reduce
operation
{

auto grammarIt = grammar . find ( actionIt - >


second . number ) ;
if ( grammarIt != grammar . end () )
{

for ( size_t j =0; j < grammarIt - > second .


rightSide . size () ; j ++)
{
parsingStack . pop () ;
}
auto tmpTop = parsingStack . top () ;
auto gotoIt = gotoTable [ tmpTop ]. find (
grammarIt - > second . leftSide ) ;
if ( gotoIt != gotoTable [ tmpTop ]. end () )
{
parsingStack . push ( gotoIt - > second )
;
}
else {
cout < < " Item not found in Goto
Table ! " << endl ;
cout < < " Parsing operation
failed ! " << endl ;
error = true ;
}
}
else
{
cout < < " Grammar rule not found " << endl ;
}
}

9
Informe del compilador

else if ( actionIt - > second . type ==3) // Accept


{
process = " Parsing operation succeeded ! " ;
break ;
}
}
else
{

process = " Parsing operation failed in


line " + to_string ( buffer [ i ].
number_line ) + " . " ;
error = true ;
}
}
return process ;
}

Explicación: La función analyze .


En esta parte implementamos la función que se encarga de leer la tabla generada
(SLR) y determinar aquellas cadenas que cumplen con las reglas de la gramática
correspondiente.

3. Análisis semántico

3.1. Tabla de simbolos


string Parser :: analyze ( vector < Token > buffer )
# ifndef SYMBOLTABLE_H
# define SYMBOLTABLE_H
# include < iostream >
# include < unordered_map >
# include < string >

using namespace std ;


class PropertiesRecord
{
public :
string id ;

10
Informe del compilador

string token ;
string dataType ;
bool declared ;
PropertiesRecord ( string i , string t )
{
id = i ;
token = t ;
// dataType =d;
// initialized = init ;
}

};

class SymbolTable
{
public :
SymbolTable () ;
void insert_symTab ( string key , PropertiesRecord p )
;
bool lookup_symTab ( string key ) ;
private :
unordered_map < string , PropertiesRecord > symTab ;

};
# endif // SYMBOLTABLE_H

En esta parte se define la tabla de sı́mbolos que contiene la información necesaria


para determinar las propiedades de las distintas entidades que participan en las
distintas fases de análisis. Desde la fase de análisis léxico se almacena información en
esta tabla referente a los identificadores y sus propiedades, para esto se implementa
la clase PropertiesRecord que almacena estas propiedades y una estructura hash
(unordered map) que contiene toda la información del código analizado para la fase
semántica, con los métodos básicos para insertar y buscar. Utilizando los datos de
esta tabla se define una regla semántica para detectar aquellas variables que son
declaradas por segunda vez.

11
Informe del compilador

4. Conclusiones
La función de un compiladores es leer un programa escrito es un lenguaje, en
este caso el lenguaje fuente, y lo traduce a un programa equivalente en otro
lenguaje, el lenguaje objeto.
Una sintaxis y lenguajes especı́ficos, ya que, al igual que el lenguaje humano, si
no lo escribimos correctamente el compilador no hará lo que deseamos. Y que
en la compilación hay dos partes: Análisis y Sı́ntesis. La parte del análisis divide
al programa fuente en sus elementos componentes y crea una representación
intermedia.

5. Referencias
1. Compiladores, Principios, técnicas y herramientas, Alfred V. Aho, Ravi Sethi,
Jeffrey D. Ullman. Addison – Wesley iberoamericana.
2. http://www.dlsi.ua.es/docencia/asignaturas/comp1/comp1.html
3. http://www.cps.unizar.es/ ezpeleta/COMPI

12

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