Está en la página 1de 15

Instituto Tecnológico de Pachuca

Ingeniería en Sistemas Computacionales

Programación de Sistemas

UNIDAD 4: ANALIZADOR SINTACTICO

Actividad-U4-04: Desarrollo de un ANALIZADOR SINTACTICO

Catedrático: M. en C. Carlos I. Rivas Palacios

Equipo: 1

 Cabrera Ojeda Adrián


 Landeros González Anahid
 Martínez Moctezuma Karen
 Zarate Islas Irvyn
19 de octubre del 2010.

Fundamentación teórica:
Análisis Sintáctico.

Todo lenguaje de programación tiene reglas que describen la estructura sintáctica de


programas bien formados. En Pascal, por ejemplo, un programa se compone de bloques,
un bloque de proposiciones, una proposición de expresiones, una expresión de
componentes léxicos, y así sucesivamente. Se puede describir la sintaxis de las
construcciones de los lenguajes de programación por medio de gramáticas de contexto
libre o notación BNF ( Backus-Naur Form).
Las gramáticas ofrecen ventajas significativas a los diseñadores de lenguajes y a los
desarrolladores de compiladores.

• Las gramáticas son especificaciones sintácticas y precisas de lenguajes de


programación.
• A partir de una gramática se puede generar automáticamente un analizador sintáctico.
• El proceso de construcción puede llevar a descubrir ambigüedades.
• Una gramática proporciona una estructura a un lenguaje de programación, siendo más
fácil generar código y detectar errores.
• Es más fácil ampliar/modificar el lenguaje si está descrito con una gramática.

La mayor parte de este tema está dedicada a los métodos de análisis sintáctico de uso
típico en compiladores. Primero se introducen los conceptos básicos, después las
técnicas adecuadas para la aplicación manual. Además como los programas pueden
contener errores sintácticos, los métodos de análisis sintáctico se pueden ampliar para
que se recuperen de los errores sintácticos más frecuentes.

¿Qué es el analizador sintáctico?


Es la fase del analizador que se encarga de chequear el texto de entrada en base a unan
gramática dada. Y en caso de que el programa de entrada sea válido, suministra el árbol
sintáctico que lo reconoce.

En teoría, se supone que la salida del analizador sintáctico es alguna representación del
árbol sintáctico que reconoce la secuencia de tokens suministrada por el analizador
léxico.

En la práctica, el analizador sintáctico también hace:

• Acceder a la tabla de símbolos (para hacer parte del trabajo del analizador
semántico).
• Chequeo de tipos ( del analizador semántico).
• Generar código intermedio.
• Generar errores cuando se producen.

En definitiva, realiza casi todas las operaciones de la compilación. Este método de trabajo
da lugar a los métodos de compilación dirigidos por sintaxis.
Gramática libre de contexto.

La estructura de un programa de computadora está dada en términos de


procedimientos, sentencias, expresiones, etc.
El metalenguaje es una forma de especificar lenguajes de libre contexto y se definió
originalmente utilizando ->.

Generalmente se atribuye a John Backus y Peter Naur el crédito por el desarrollo de esta
notación como una forma de describir la sintaxis del lenguaje de programación Algol.

A diferencia de los lenguajes naturales como el español, todas las cadenas de caracteres
validas en el lenguaje de programación pueden especificarse empleando una gramática
de libre contexto. Sin embargo, las gramáticas para los lenguajes de programación
especifican las cadenas semánticamente incorrectas, así como lo hacen las gramáticas
para los lenguajes naturales.

Manejo de errores sintácticos

Si un compilador tuviera que procesar sólo programas correctos, su diseño e implantación


se simplificarían mucho. Pero los programadores a menudo escriben programas
incorrectos, y un buen compilador debería ayudar al programador a identificar y localizar
errores. Es más, considerar desde el principio el manejo de errores puede simplificar la
estructura de un compilador y mejorar su respuesta a los errores.

Los errores en la programación pueden ser de los siguientes tipos:


• Léxicos, producidos al escribir mal un identificador, una palabra clave o un operador.
• Sintácticos, por una expresión aritmética o paréntesis no equilibrados.
• Semánticos, como un operador aplicado a un operando incompatible.
• Lógicos, puede ser una llamada infinitamente recursiva.

El manejo de errores de sintaxis es el más complicado desde el punto de vista de la


creación de compiladores. Nos interesa que cuando el compilador encuentre un error, se
recupere y siga buscando errores. Por lo tanto el manejador de errores de un analizador
sintáctico debe tener como objetivos:

• Indicar los errores de forma clara y precisa. Aclarar el tipo de error y su localización.
• Recuperarse del error, para poder seguir examinando la entrada.
• No ralentizar significativamente la compilación.

Un buen compilador debe hacerse siempre teniendo también en mente los errores que se
pueden producir; con ello se consigue:

• Simplificar la estructura del compilador.


• Mejorar la respuesta ante los errores.

Archivos que maneja:

*.txt
Archivo de captura:
/*condicion*/ if else int( n = = 20 ){

/*operacion*/ res = ( var * 5.0987 ) / 2E656 ;

op = ( rs + 1 ) ;

/*fin del programa*/

/*hola como esta*/

//bobobobob

Reportes:

Código del programa


Interfaz:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JFileChooser;
import java.io.BufferedReader;
import java.io.FileReader;
import javax.swing.JFileChooser;
import java.net.URL;
import java.net.MalformedURLException;
import java.io.*;
import java.util.StringTokenizer;
public class Interfaz extends JFrame implements ActionListener{
public JTextArea textCodigo,textError;
public JLabel codigo,tokens,tipo,simbolos,errores;
public JList listToken,listTipo;
public JTable tableToken,tableId,califas,foxxis;
public JScrollPane scroll1,scroll2,scroll3,scroll4;
public JButton botonAbrir,botonLexico,botonSintactico,botonSemantico,botonGenerador;

public Interfaz(){
setSize(800,600);
setLocationRelativeTo(null);
setTitle("Analizador Lexicogrfico");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ini();
}

public static void main(String[] args) {


try {
UIManager.setLookAndFeel("com.jtattoo.plaf.noire.NoireLookAndFeel");
} catch (Exception e) {
e.printStackTrace();
}

Interfaz i1= new Interfaz();


i1.setVisible(true);
}

public void ini(){

setLayout(null);
botonAbrir = new JButton(); botonLexico = new JButton(); botonSintactico = new
JButton(); botonSemantico = new JButton(); botonGenerador=new JButton();
//fieldTokens= new JTextArea(); fieldSimbolos= new JTextArea(); fieldErrores=new JTextArea();
textCodigo=new JTextArea(); textError=new JTextArea();
//fieldTokens.setText("");
codigo=new JLabel("Introduzca el codigo aqui");
tokens=new JLabel("Tokens");
simbolos=new JLabel("Tabla de simbolos");
errores= new JLabel("Errores");
tableId = new JTable(140,1);
tableToken = new JTable(140,2);
scroll1 = new JScrollPane(tableToken);
scroll2 = new JScrollPane(tableId);
scroll3 = new JScrollPane(textCodigo);
scroll4 = new JScrollPane(textError);

scroll1.setBounds(430,50,250,200);
add(scroll1);
scroll2.setBounds(10,320,250,200);
add(scroll2);
scroll3.setBounds(10,50,320,200);
add(scroll3);
scroll4.setBounds(430,320,320,200);
add(scroll4);

codigo.setBounds(10,10,320,30);
codigo.setText("Introduce el codigo");
add(codigo);

tokens.setBounds(430,10,250,30);
tokens.setText("Tokens");
add(tokens);

simbolos.setBounds(10,280,250,30);
simbolos.setText("Tabla de simbolos");
add(simbolos);
errores.setBounds(430,280,250,30);
errores.setText("Errores");
add(errores);

botonAbrir.setBounds(340,80,80,20);
botonAbrir.setText("Abrir");
botonAbrir.addActionListener(this);
add(botonAbrir);

botonLexico.setBounds(700,80,80,20);
botonLexico.setText("Lexico");
botonLexico.addActionListener(this);
add(botonLexico);

botonSintactico.setBounds(700,120,80,20);
botonSintactico.setText("Sintactico");
botonSintactico.addActionListener(this);
add(botonSintactico);
}

public void leccico(){


Lexico l1=new Lexico();
String toks="", idents="", errors="";
String[] palabra, valor, ids, errs;
int i=0,n=0;

if(l1.filtrarC(textCodigo.getText())==true){
textError.setText("No cierra comentario");
}else{
String cod=l1.filtrar(textCodigo.getText());
StringTokenizer tok = new StringTokenizer(cod);

palabra= new String[tok.countTokens()];


while (tok.hasMoreTokens()){
palabra[i]=tok.nextToken();
i++;
}
valor=l1.tipo(palabra);
ids=l1.ids(palabra,valor);
errs=l1.errores(palabra,valor);

for(i=0;i<palabra.length;i++){
System.out.print(palabra[i]+" ");
tableToken.setValueAt(palabra[i],i,0);
System.out.println(valor[i]);
tableToken.setValueAt(valor[i],i,1);
}
for(i=0;i<(ids.length);i++){
System.out.print(ids[i]+" ");
tableId.setValueAt(ids[i],i,0);
}
for(i=0;i<(errs.length);i++){
System.out.print(errs[i]+" ");
errors=(errors+errs[i]+"\n");
}
textError.setText(errors);// caracter invalido, token invalido, fin del programa
}
}

public void zintactico(){


Lexico l2= new Lexico();
String[] valor,palabra,entrada;
String[][] renglon;
int i=0,j=0,k=0,p;
String[][] produccion={{"T E'","","","T E'","","","",""},
{"","+ T E'","","",null,null,"- T E'",""},
{"F T'","","","F T'","","","",""},
{"",null,"* F T'","",null,null,null,"/ F T'"},
{"id","","","( E ).","","","",""}};
StringTokenizer tok = new StringTokenizer(textCodigo.getText());

palabra= new String[tok.countTokens()];


entrada=new String[palabra.length];
renglon = new String[textCodigo.getLineCount()-1][palabra.length];
while (tok.hasMoreTokens()){
palabra[i]=tok.nextToken();
i++;
}
valor=l2.tipo(palabra);
for(i=0;i<palabra.length;i++){
if(palabra[i].charAt(0)!=';'){
if(valor[i].equals("identificador") || valor[i].equals("numero entero")){
renglon[j][k]="id";
k++;
}else{
renglon[j][k]=palabra[i];
k++;
}

}else{
j++;
k=0;
}
}
for(i=0;i<textCodigo.getLineCount()-1;i++){
k=0;
for(p=0;p<entrada.length;p++){
entrada[p]=null;
}
for(j=0;j<palabra.length;j++){
if(renglon[i][j]!=null){
entrada[k]=renglon[i][j];
k++;
}

}
entrada[k]="$";
if (renglon[0][0].equals("=")){
System.out.println("Mas de un identificador");
}else{
Sintactico s1=new Sintactico();
s1.sintactico();
s1.area1.setText(s1.producir(entrada,produccion));

}
}
for(i=0;i<entrada.length;i++){
}

public void actionPerformed(ActionEvent x) {


boolean in=true;

if(x.getSource()==botonAbrir){
String linea;
textCodigo.setText("");
LecturaArch archivo = new LecturaArch();
JFileChooser chooser = new JFileChooser();

if(chooser.showOpenDialog(null)==JFileChooser.APPROVE_OPTION){
linea="";
try{
linea=chooser.getSelectedFile().toString();
}catch(Exception mfue){
System.err.println("No se puede abrir");
}
if(linea != null){
System.out.println(linea);
textCodigo.append(archivo.Lectura(linea));
}
}
}else{
if (x.getSource()==botonLexico){
leccico();
}else{
if(x.getSource()==botonSintactico){
zintactico();
}
}
}

}
}

Analizador sintáctico:

import javax.swing.JOptionPane;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.lang.*;
public class Sintactico {
JFrame ventana;
JTextArea area1;
JScrollPane scr1;
JLabel label1;

String[] pila=new String[20];


int tope, actual=2;
int noTerminal, simbolo;
int i,k=0,j=0;
String palabra;

String producir(String[] entrada,String[][] produccion){


String reglas="";
pila[0] = "$"; tope=1;
pila[1] = "E"; tope=2;
for(i=0;i<entrada.length;i++){
System.out.print(entrada[i]);
}
while(tope!=0 && j<40){
System.out.print("pila: ");
reglas=reglas+"\nPila: ";
for(i=0;i<pila.length;i++){
if(pila[i]!=null){
reglas=reglas+" "+pila[i];
System.out.print(" "+pila[i]);
}
}
if ((int)pila[tope-1].charAt(0)<65 || (int)pila[tope-1].charAt(0)>90){ //es terminal
System.out.println("\n"+pila[tope-1]);
if(pila[tope-1]!=null)
reglas=reglas+"\n"+pila[tope-1];
if (entrada[actual].equals(pila[tope-1])){
actual++;
pila[tope-1]=null; tope--;
}else{
System.out.println("\n"+"Error");
reglas=reglas+"\n"+"Error";
System.exit(0);
}
}else{
System.out.print("\n"+pila[tope-1]+" ==> ");
reglas=reglas+"\n"+pila[tope-1]+" ==> ";
if(pila[tope-1].equals("E"))
noTerminal=0;
if(pila[tope-1].equals("E'"))
noTerminal=1;
if(pila[tope-1].equals("T"))
noTerminal=2;
if(pila[tope-1].equals("T'"))
noTerminal=3;
if(pila[tope-1].equals("F"))
noTerminal=4;
if(entrada[actual].equals("id"))
simbolo=0;
if(entrada[actual].equals("+"))
simbolo=1;
if(entrada[actual].equals("*"))
simbolo=2;
if(entrada[actual].equals("("))
simbolo=3;
if(entrada[actual].equals(")"))
simbolo=4;
if(entrada[actual].equals("$"))
simbolo=5;
if(entrada[actual].equals("-"))
simbolo=6;
if(entrada[actual].equals("/"))
simbolo=7;

System.out.println(produccion[noTerminal][simbolo]);

reglas=reglas+""+produccion[noTerminal][simbolo];
tope--;
if(produccion[noTerminal][simbolo]!=null){
for (i=produccion[noTerminal][simbolo].length()-1;i>0;i--){
if(produccion[noTerminal][simbolo].charAt(i)==' '){
if(produccion[noTerminal]
[simbolo].charAt(i+2)==' ' || produccion[noTerminal][simbolo].charAt(i+2)=='.'){
tope++;
pila[tope-1]= produccion[noTerminal]
[simbolo].charAt(i+1)+"";
}else{
tope++;
pila[tope-1]= produccion[noTerminal]
[simbolo].charAt(i+1)+""+produccion[noTerminal][simbolo].charAt(i+2);
}
}
}//fin del for
k=0;
while((k<produccion[noTerminal][simbolo].length()-1) &&
produccion[noTerminal][simbolo].charAt(k+1)!=' '){
k++;
}
palabra="";
for(i=0;i<=k;i++){
palabra=palabra+""+produccion[noTerminal]
[simbolo].charAt(i);
}
tope++;
pila[tope-1]=palabra;
}else{
pila[tope]=null;
}
}
j++;
}
if(actual==entrada.length)
System.out.println("Aceptado");
reglas=reglas+"\n"+"Aceptado";
return reglas;
}

public void sintactico(){


ventana = new JFrame ("Analizador Sintactico");
ventana.setSize(800,600);
ventana.setLocationRelativeTo(null);
ventana.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
ventana.setLayout(null);

label1 = new JLabel("Gramatica");


label1.setBounds(10,10,150,30);
ventana.add(label1);

area1 = new JTextArea();


area1.setEditable(false);

scr1 = new JScrollPane(area1);


scr1.setBounds(10,50,500,450);
ventana.add(scr1);

ventana.setVisible(true);
}

public static void main(String[] args) {


String[] entrada={"id","=","id","-","id","/","id","+","id","*","id","$"};
String[][] produccion={{"T E'","","","T E'","","","",""},
{"","+ T E'","","",null,null,"- T E'",""},
{"F T'","","","F T'","","","",""},
{"",null,"* F T'","",null,null,null,"/ F T'"},
{"id","","","( E ).","","","",""}};

if (!entrada[1].equals("=")){
System.out.println("Mas de un identificador");
}else{
Sintactico s1=new Sintactico();
s1.producir(entrada,produccion);
}

}
}
Resultados

Resultado del analizador léxico:

Resultado del analizador sintáctico:


General output:

C:\Documents and Settings\IRVYN ZARATE\Escritorio\ent302.txt


/*condicion*/ if else int( n = = 20 ){
/*operacion*/ res = ( var * 5.0987 ) / 2E656 ;
op = ( rs + 1 ) ;
/*fin del programa*/
}
/*hola como esta*/
//bobobobob
if palabra reservada
n identificador
= operador comparacion
= operador comparacion
20 numero entero
{ operador agrupacion
res identificador
= operador comparacion
( operador agrupacion
var identificador
* operador aritmetico
5987 numero entero
) operador agrupacion
/ operador aritmetico
256 numero entero
; caracter especial
op identificador
= operador comparacion
( operador agrupacion
rs identificador
+ operador aritmetico
1 numero entero
) operador agrupacion
; caracter especial
} operador agrupacion
n res var op rs null id=id-id/id+id*id$pila: $ E
E ==> T E'
pila: $ E' T
T ==> F T'
pila: $ E' T' F
F ==> id
pila: $ E' T' id
id
pila: $ E' T'
T' ==> null
pila: $ E'
E' ==> - T E'
pila: $ E' T -
-
pila: $ E' T
T ==> F T'
pila: $ E' T' F
F ==> id
pila: $ E' T' id
id
pila: $ E' T'
T' ==> / F T'
pila: $ E' T' F /
/
pila: $ E' T' F
F ==> id
pila: $ E' T' id
id
pila: $ E' T'
T' ==> null
pila: $ E'
E' ==> + T E'
pila: $ E' T +
+
pila: $ E' T
T ==> F T'
pila: $ E' T' F
F ==> id
pila: $ E' T' id
id
pila: $ E' T'
T' ==> * F T'
pila: $ E' T' F *
*
pila: $ E' T' F
F ==> id
pila: $ E' T' id
id
pila: $ E' T'
T' ==> null
pila: $ E'
E' ==> null
pila: $
$
Aceptado
/*condicion*/ifid==id{/*operacion*/id=(id*id)/id$nullnullnullnullnullnullnullnullnullnullnullnullpila: $ E
E ==> T E'
pila: $ E' T
T ==> F T'
pila: $ E' T' F
F ==> id
pila: $ E' T' id
id
pila: $ E' T'
T' ==>

Conclusiones

En el análisis sintáctico lleva acabo el análisis de sintaxis en nuestro


lenguaje de programación desde nuestro programa fuente
representándolo en una gramática en la cual esta lo analiza en
nuestras reglas que estipulamos en el análisis gramatical para llevar a
cabo su función para aceptar las instrucciones ingresados por el
archivo fuente, en esta parte también aprendimos como aplicar las
estructuras de datos en la realización y verificamos los lenguajes de
programación no son muy distintos a los lenguajes naturales.

Con esta herramienta se da nuestro análisis requerido para la segunda


etapa de los compiladores en el análisis sintáctico en donde lo
almacenamos en una pila en la cual contiene una entrada y una
producción.

También podría gustarte