1 - Análisis-Semántico
1 - Análisis-Semántico
1 - Análisis-Semántico
Carrera:
Ingeniera en Sistemas Computacionales
Asignatura:
Lenguajes y Autmatas II
ndice
Contenido
Introduccin.......................................................................................3
Actividad 1.........................................................................................4
Detectar Errores Semnticos...................................................................4
Ejemplos De La Actividad Uno...............................................................7
Actividad 2.......................................................................................23
Disear Y Seleccionar Informacin Sobre La Construccin De Un Analizador
Semntico........................................................................................23
Ejemplos De La Actividad Dos.............................................................28
Actividad 3.......................................................................................46
Reconocer El Manejo De Tipos En Las Expresiones Y El Uso De Operadores.......46
Actividad 4.......................................................................................54
Establecer Las Reglas Para La Conversin De Tipos (Casting) En Expresiones....54
Conversiones Implcitas....................................................................56
Conversiones Explcitas....................................................................56
Excepciones De Las Conversiones De Tipos En Tiempo De Ejecucin............58
Actividad 5.......................................................................................59
Agregar Acciones Semnticas A La Estructura De La Gramtica......................59
Actividad 6.......................................................................................70
Manipular La Tabla De Conversin De Smbolos Y De Errores Y Direcciones.......70
Actividad 7.......................................................................................65
Integrar Equipos De Trabajo Para La Construccin De Un Analizador Semntico.. 65
Actividad 8.......................................................................................81
Propuesta De Proyecto Para El Analizador Lxico Y Sintctico........................81
Conclusiones....................................................................................82
Bibliografa....................................................................................83
Actividad 1.
Aplicar los tipos de notacin para la conversin de expresiones: Infija, prefija y posfija.
2
Los esquemas de generacin dependen de cada lenguaje. Tomaremos
algunos esquemas de generacin del lenguaje C.
Variables y constantes
Las variables y constantes deben separarse de tal manera que queden
las expresiones una por una de manera simple.
Por ejemplo int a,b,c; se descompone a int a; int b; intc;
respectivamente.
Expresiones
En esta funcin recibe una cadena que representa una lnea de cdigo
intermedio y toma las medidas oportunas para que ese cdigo se utilice.
Estas medidas pueden ser escribir la lnea en un fichero adecuado,
almacenar la instruccin en una lista que despus se pasar a otros
mdulos, o cualquier otra que necesitemos en nuestro compilador.
Expresiones aritmticas
Son aquella donde los operadores que intervienen en ella son numricos, el
resultado es un nmero y los operadores son aritmticos. Los operadores
aritmticos ms comnmente utilizados son: +, - , * , / y %.
Comenzamos el estudio por las expresiones aritmticas. Lo que tendremos
que hacer es crear por cada tipo de nodo un mtodo que genere el cdigo
para calcular la expresin y lo emita. Ese cdigo dejar el resultado en un
registro, cuyo nombre devolver el mtodo como resultado.
Para reservar estos registros temporales, utilizaremos una funcin, reserva.
En principio bastar a con que esta funcin devuelva un registro distinto
cada vez que se la llame.
Cada nodo generar el cdigo de la siguiente manera:
Por cada uno de sus operandos, llamara al mtodo correspondiente
para que se evale la sub expresin. Si es necesario, reservara un
registro para guardar su resultado.
Emitir las instrucciones necesarias para realizar el clculo a partir
de los operandos.
Instrucciones de asignacin
La sintaxis general de la instruccin de asignacin es:
nombre_de_la_variable = valor
El valor a la derecha del signo igual puede ser una constante, otra variable
3
o una expresin que combine constantes y variables, pero siempre la
variable y su valor deben ser del mismo tipo de dato.
Ejemplos:
edad% = 5
area! = 12.3
nombre$ = Pedro
Instrucciones de control
Esta forma de programacin slo permite resolver problemas sencillos.
Para resolver problemas ms complejos, nos puede interesar que
dependiendo de los valores de los datos, se ejecuten unas instrucciones u
otras.
Las instrucciones condicionales nos van a permitir representar ste tipo de
comportamiento. Sentencias IF y SWITCH. En otros casos, nos
encontraremos con la necesidad de repetir una instruccin o instrucciones
un nmero determinado de veces. En stos casos utilizaremos
instrucciones de control iterativas o repetitivas (ciclos). Sentencias WHILE,
DO-WHILE y FOR.
Funciones
Las funciones pueden reducir a en lnea, lo que se hace que expandir el cdigo
original de la funcin.
Las funciones se descomponen simplificando los parmetros de manera individual
al igual que el valor de retorno.
Actividad 1
4
package infixpostfix4;
import java.util.Scanner;
import java.util.Stack;
//Entrada de datos
System.out.println("*Escribe una expresin algebraica: ");
Scanner leer = new Scanner(System.in);
try {
//Algoritmo Infijo a Postfijo
while (!E.isEmpty()) {
switch (pref(E.peek())){
case 1:
P.push(E.pop());
break;
case 3:
case 4:
while(pref(P.peek()) >= pref(E.peek())) {
S.push(P.pop());
}
P.push(E.pop());
break;
case 2:
while(!P.peek().equals("(")) {
S.push(P.pop());
}
P.pop();
E.pop();
break;
5
default:
S.push(E.pop());
}
}
//Mostrar resultados:
System.out.println("Expresion Infija: " + infix);
System.out.println("Expresion Postfija: " + postfix);
}catch(Exception ex){
System.out.println("Error en la expresin algebraica");
System.err.println(ex);
}
}
6
Actividad 2.
7
Informalmente, se llamar atributos de un smbolo de la gramtica a toda
informacin aadida en el rbol de derivacin por el analizador semntico,
asociada a los smbolos de los nodos anotados. Un componente importante de
las gramticas de atributos es el algoritmo de clculo de los valores.
Ejemplos de atributos:
Ejemplo:
a) numero-> digito
numero.valor = digito.valor
Las funciones semnticas relacionan los valores de los atributos definidos sobre la
gramtica atribuida y van asociadas a producciones de la gramtica atribuida.
Definicin formal
8
A atributos asociados a los smbolos terminales y no terminales
9
desarrollo de procesadores de lenguaje ofrecen la posibilidad de especificar, de un
modo imperativo en lugar de declarativo, las reglas semnticas de las definiciones
dirigidas por sintaxis (gramticas atribuidas). Esta notacin es la que se conoce
como esquema de traduccin (dirigida por sintaxis): una gramtica libre de
contexto en la que se asocian atributos con los smbolos gramaticales y se
insertan rutinas semnticas dentro de las partes derecha de las producciones
[Aho90]. Las rutinas semnticas son, a su vez, fragmentos de cdigo que el
desarrollador del compilador escribe normalmente entre llaves {} dejando
explcito el momento en el que la herramienta ha de ejecutar la misma, durante su
proceso de anlisis.
10
Una rutina semntica no debe utilizar atributos sintetizados de un smbolo
gramatical que est a la derecha de ella.
Un atributo sintetizado para el no terminal de la izquierda slo se puede calcular
posteriormente a los atributos de los que depende. La rutina semntica que
calcula estos atributos se suele colocar al final del lado derecho de la produccin.
La Tabla de Smbolos
11
nombre. Con este enfoque, las palabras clave deben estar en la tabla de smbolos
antes de que comience el anlisis lxico. En ocasiones, si el analizador lxico
reconoce las palabras clave reservadas, entonces no necesitan aparecer en la
tabla de smbolos. Si el lenguaje no convierte en reservadas las palabras clave,
entonces es indispensable que las palabras clave se introduzcan en la tabla de
smbolos advirtiendo su posible uso como palabras clave.
12
/**
*
* @author Invitado
*/
public class Tokens {
static String linea = "38+2*3";
//usando delimitadores y regresandolos como tokens
static StringTokenizer tokens3 = new StringTokenizer(linea, "+-*/=", true);
static final int NUMERO=0;
static final int OPERADOR=1;
static String lexema="";
13
/* // separacion de tokens con StringTokenizer usando el espacio por defecto
como separador de tokens
StringTokenizer tokens = new StringTokenizer(linea);
while(tokens.hasMoreTokens())
System.out.println(tokens.nextToken());
System.out.println();
//usando delimitadores
StringTokenizer tokens2 = new StringTokenizer(linea, "+=");
while(tokens2.hasMoreTokens())
System.out.println(tokens2.nextToken().trim());
System.out.println();
*/
int token=lexico();
do
{
System.out.println(token+" "+lexema);
token=lexico();
}
while (!lexema.equals(""));
}
}
14
Figura E.1 Pantallazo de Cdigo fuente
Figura E.2 Resultados del programa ejecutado muestra los tokens utilizados en
este mismo cdigo.
Ejemplo 2
15
Cdigo Fuente:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package tabla.de.tokens;
import java.util.*;
/**
*
* @author Invitado
*/
public class TablaDeTokens {
16
{
return this.lexema;
}
public static final int p=23; // el tamao del arreglo de hash (un nmero primo)
17
// creamos 2 datos de prueba
ElementoTs a=new ElementoTs("ident01");
ElementoTs b=new ElementoTs("ident02");
18
Atributos axVar = ts.get("xVar");
System.out.println("xVar es "+axVar.tipo+" "+axVar.longitudBytes);
}
}
Figura E.4 Resultado del programa que busca y analiza Tokens en su cdigo
fuente.
Ejemplo 3
Cdigo Fuente:
19
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.IO;
namespace analizador_lexico
{
publicpartialclassForm1 : Form
{
public Form1()
{
InitializeComponent();
}
RegexLexer csLexer = newRegexLexer();
bool load;
List<string> palabrasReservadas;
csLexer.Compile(RegexOptions.Compiled | RegexOptions.Singleline |
RegexOptions.ExplicitCapture);
20
load = true;
AnalizeCode();
tbxCode.Focus();
}
}
privatevoid AnalizeCode()
{
dataGridView1.Rows.Clear();
//lvToken.Items.Clear();
int n = 0, e = 0;
foreach (var tk1 in csLexer.GetTokens(tbxCode.Text))
{
if (tk1.Name == "ERROR") e++;
if (tk1.Name == "IDENTIFICADOR")
if (palabrasReservadas.Contains(tk1.Lexema))
tk1.Name = "RESERVADO";
dataGridView1.Rows.Add(tk1.Name,tk1.Lexema,tk1.Linea,tk1.Columna,tk1.Index);
//string cadena = tk1.Name + " " +tk1.Lexema;
//lvToken.Items.Add(cadena);
n++;
}
this.Text = string.Format("Analizador Lexico - {0} tokens {1} errores", n, e);
}//fin del metodo analizecode
namespace analizador_lexico
{
classToken
{
public Token(string name, string lexema, int index, int linea, int columna)
{
Name = name;
Lexema = lexema;
Index = index;
Linea = linea;
Columna = columna;
}
21
publicint Linea { get; privateset; }
publicint Columna { get; privateset; }
namespace analizador_lexico
{
classRegexLexer
{
Regex rex;
StringBuilder patron;
bool requiereCompilar;
List<string> TNames;
int[] GNumbers;
public RegexLexer()
{
requiereCompilar = true;
TNames = newList<string>();
}
///<summary>
/// Agrega una nueva regla para reconocer token
///</summary>
//"/[*].*?[*]/", "COMENTARIO2"
///<param name="pattern">patrn en el que debe encajar</param>
///<param name="token_name">id nico para este patrn</param>
///<param name="ignore">true para no devolver este token</param>
publicvoid AddTokenRule(string pattern, string token_name, bool ignore = false)
{
if (string.IsNullOrWhiteSpace(token_name))
thrownewArgumentException(string.Format("{0} no es un nombre vlido.", token_name));
if (string.IsNullOrEmpty(pattern))
thrownewArgumentException(string.Format("El patrn {0} no es vlido.", pattern));
if (patron == null)
patron = newStringBuilder(string.Format("(?<{0}>{1})", token_name, pattern));
else
patron.Append(string.Format("|(?<{0}>{1})", token_name, pattern));
if (!ignore)
TNames.Add(token_name);
requiereCompilar = true;
}
22
///<summary>
/// Reinicia el Lexer
///</summary>
publicvoid Reset()
{
rex = null;
patron = null;
requiereCompilar = true;
TNames.Clear();
GNumbers = null;
}
///<summary>
/// Analisa una entrada en busca de tokens validos y errores
///</summary>
///<param name="text">entrada a analizar</param>
publicIEnumerable<Token> GetTokens(string text)
{
if (requiereCompilar) thrownewException("Compilacin Requerida, llame al mtodo
Compile(options).");
if (!match.Success) yieldbreak;
while (match.Success)
{
if (match.Index > index)
{
string token = text.Substring(index, match.Index - index);
break;
}
}
23
}
}
///<summary>
/// Crea el AFN con los patrones establecidos
///</summary>
publicvoid Compile(RegexOptions options)
{
if (patron == null) thrownewException("Agrege uno o ms patrones, llame al mtodo
AddTokenRule(pattern, token_name).");
if (requiereCompilar)
{
try
{
rex = newRegex(patron.ToString(), options);
GNumbers = newint[TNames.Count];
string[] gn = rex.GetGroupNames();
requiereCompilar = false;
}
catch (Exception ex) { throw ex; }
}
}
///<summary>
/// Cuenta la cantidad de lineas presentes en un token, establece el inicio de linea.
///</summary>
privateint CountNewLines(string token, int index, refint line_start)
{
int line = 0;
for (int i = 0; i < token.Length; i++)
if (token[i] == '\n')
{
line++;
line_start = index + i + 1;
}
return line;
}
}
}
24
Actividad 3.
25
Reconocer el manejo de tipos en las expresiones y el uso de operadores.
OPERADORES DE ASIGNACIN
Este tipo de operadores permiten la asignacin de un valor especfico a una
variable. En C++ se encuentran disponibles los siguientes operadores:
26
realiza una conversin de tipo (con prdida de precisin en su caso) del izquierdo
al derecho. Es necesario resaltar que el operador C++ de asignacin simple (=) se
distingue de otros lenguajes como Pascal que utilizan el smbolo := para este
operador. Observe tambin que la asignacin simple (=) utiliza un smbolo distinto
del operador relacional de igualdad (==) [2]. Adems, en los operadores
compuesto no debe haber espacios de la forma + = y que el igual siempre va a la
derecha del resto de operandos.
OPERADORES ARITMTICOS
Los operadores aritmticos se usan para realizar clculos y operaciones con
nmeros reales y punteros. Bsicamente permiten hacer cualquier operacin
aritmtica que se necesite. Los operadores ms comunes son:
Ej.: HOLA\0! `H', `O', `L', `A', `\0! donde \0 es el carcter de terminacin
27
Identificadores:
Son los nombre dados a variables, funciones, etiquetas u otros objetos definidos
por el programador. Un identificador est formado por letras (maysculas o
minsculas), nmeros y carcter de subrayado, con la condicin de que le primer
carcter no sea un nmero.
Ej.:
Precio_Venta Verdadero
Precio Venta Falso
1Num Falso
_123 Verdadero
De un identificador, slo son significativos los primeros 32 caracteres.
Palabras reservadas:
Son palabras especiales que no se pueden usar para nombrar otros elementos del
lenguaje.
NOTA: C hace distincin entre maysculas y minsculas
Comentarios:
El compilador reconoce como comentario cualquier grupo de caracteres situados
entre \* *\ aunque estn en diferentes lneas. Se pueden definir comentarios en
una sola lnea mediante //
28
Atendiendo al nmero de operandos sobre los que acta un operador, estos se
clasifican en:
aritmticos
relacionales
lgicos
de tratamiento de bits
especiales
Los operadores, junto con los operandos, forman expresiones. En una expresin,
los operandos pueden ser constantes, variables o llamadas a funciones que
devuelvan valores. Una expresin se convierte en una sentencia cuando va
seguida de un ;. Cuando un grupo de sentencias se encierran entre llaves, { },
forman un bloque sintcticamente equivalente a una sentencia.
El valor devuelto por el operador de divisin (/) depende del tipo de operandos. Si
stos son enteros, devuelve la parte entera del cociente. Si alguno de ellos es real,
devuelve el resultado como nmero real.
X=9
29
Y=2
C - - es lo mismo que C! C - 1
BINARIOS
>, <, >=, <=, ==!=, Mayor que, Menor que, Mayor o igual que, Menor o igual que,
Igual que, Diferente que.
El resultado de una expresin relacional solo puede ser verdadero o falso, lo que
en C se identifica con los valores "0 y 0 respectivamente. La expresin a==b se
evaluar como 0 si a y b son diferentes y como distinto de 0 si son iguales.
30
Actan sobre expresiones booleanas, es decir, sobre valores V o F generados por
expresiones como las del caso anterior. Son los siguientes:
UNARIOS
!, NOT, BINARIOS, &&, AND, ||, OR,
Ej.:
X=20 x==y ! F(0)
Y=4 x=y! V
Z=5 x== (y*z)! V
Los operadores and, or y not, se rigen por la misma tabla de verdad que
gobierna los operadores lgicos equivalentes. La diferencia entre unos y otros
31
consiste en que estos tres actan a nivel de bits individuales y no sobre valores
completos (&&, ||, !). As, las variables a y b almacenan respectivamente los
valores a ! 0xA1B2
B ! 0xF0F0
Ej:
a ! 0xA1B2
b ! 0x1234
a^b ! 0xB386
Los operadores de desplazamiento (>>, <<) derecha, izquierda, mueven todos los
bits de una variable a la derecha o a la izquierda, respectivamente, un nmero de
posiciones determinado. Su formato general es:
variable<<n
variable>>n
Ej.:
32
a=b<<4! almacena en a el contenido de b despus de realizar un
desplazamiento de b de 4 bits a la izquierda.
Ejemplo:
Sea a una variable declarada como entera (con signo) que almacena el valor
hexadecimal A1B2, con lo que a! 0xA1B2
Ejemplo
33
m+=5 equivale a m=m+5
m>>=(2*x+1)equivale a m=m>>(2*x+1)
INSTRUCCIONES DE E/S
- DE SALIDA:
Ejemplo:
34
El valor de la variable es: 3
TIPOS DE IDENTIFICADORES
%S ! nos permite representar una cadena de caracteres (un array de char (varias
letras)).
%LI ! muestran enteros largos (long int). Si un entero tiene 2 byte, un entero largo
tiene 4 byte.
%LT ! representamos un double.
%2.2f 25.38261
35
escala (2) y precisin (2)
%.2f si no me importa el nmero de parte entera que saque.
Esto se llama flash
\r ! para indicar un retorno de carro, que es un cdigo ASCII 13. Cuando por
ejemplo, pulsa intro. Cuando se pone \n, es un \r y un salto de lnea.
\ \
- DE ENTRADA:
SCANF tambin est en STDIO.H. Nos sirve para introducir datos por el teclado,
cualquier tipo de variable. Su formato es:
36
Dentro de esta cadena, lo nico que nos admite son los identificadores (%d, %i,
etc), que son los mismos que en printf.
scanf(%d, &variable);
donde & es direccin de (variable). Si no se pone esto, no lo hace; toma variable
como direccin y no lo ejecuta correctamente.
scanf/%d, cadena);
cadena 20 ! aqu no se pone &, por que el nombre del array de caracteres es un
puntero a la posicin del array (esto es para introducirlo de golpe).
Si queremos meter carcter a carcter a carcter, ponemos scanf(%d, cadena)
Slo en estas situaciones es la excepcin; por regla general siempre &.
Para introducir ms de una variable en un scanf:
scanf(%d %d %d %d, var1, var2, var3, var4);
Pero es preferible hacer varios scanf, 1 por variable. Se pueden introducir
diferentes identificadores. Hay algunas veces que en el buffer del teclado se
quedan 2 retornos de carro almacenados, esto implica que se salten algunas
lneas. Para solucionarlo ponemos:
fflush(stdin); siempre encima de scanf.
Una excepcin a esto es cuando queremos leer ms de un carcter del teclado,
teclas especiales (intro, sangra, etc.)
Si ponemos scanf(3d, &var), estamos limitando la introduccin a tres dgitos.
El lenguaje ensamblador, o assembler (en ingls assembly language y la
abreviacin asm), es un lenguaje de programacin de bajo nivel. Consiste en un
conjunto de mnemnicos que representan instrucciones bsicas para los
computadores, microprocesadores, microcontroladores y otros circuitos integrados
programables. Implementa una representacin simblica de los cdigos de
mquina binarios y otras constantes necesarias para programar una arquitectura
de processador y constituye la representacin ms directa del cdigo mquina
especfico para cada arquitectura legible por un programador. Cada arquitectura
de processador tiene su propio lenguaje ensamblador que usualmente es definida
por el fabricante de hardware, y est basada en los mnemnicos que simbolizan
los pasos de procesamiento (las instrucciones), los registros del procesador, las
posiciones de memoria y otras caractersticas del lenguaje. Un lenguaje
ensamblador es por lo tanto especfico de cierta arquitectura de computador fsica
(o virtual). Esto est en contraste con la mayora de los lenguajes de programacin
de alto nivel, que idealmente son porttiles.
37
Un programa utilitario llamado ensamblador es usado para traducir sentencias del
lenguaje ensamblador al cdigo de mquina del computador objetivo. El
ensamblador realiza una traduccin ms o menos isomorfa (un mapeo de uno a
uno) desde las sentencias mnemnicas a las instrucciones y datos de mquina.
Esto est en contraste con los lenguajes de alto nivel, en los cuales una sola
declaracin generalmente da lugar a muchas instrucciones de mquina.
Muchos sofisticados ensambladores ofrecen mecanismos adicionales para facilitar
el desarrollo del programa, controlar el proceso de ensamblaje, y la ayuda de
depuracin. Particularmente, la mayora de los ensambladores modernos incluyen
una facilidad de macro (descrita ms abajo), y se llaman macro ensambladores.
Fue usado principalmente en los inicios del desarrollo de software, cuando an no
se contaba con potentes lenguajes de alto nivel y los recursos eran limitados.
Actualmente se utiliza con frecuencia en ambientes acadmicos y de
investigacin, especialmente cuando se requiere la manipulacin directa de
hardware, alto rendimiento, o un uso de recursos controlado y reducido. Tambin
es utilizado en el desarrollo de controladores de dispositivo (en ingls, device
drivers) y en el desarrollo de sistemas operativos, debido a la necesidad del
acceso directo a las instrucciones de la mquina. Muchos dispositivos
programables (como los microcontroladores) an cuentan con el ensamblador
como la nica manera de ser manipulados.
Ejemplo 1
38
Codigo del programa, se insertan las libreras correspondientes, se inicializan las
variables y se muestran en pantalla con la instruccion cout.
39
Actividad 4.
Establecer las reglas para la conversin de tipos (casting) en expresiones.
( <tipo_de_dato> ) <expresin>;
De esta forma, se consigue cambiar el tipo de dato del valor resultante de evaluar
la <expresin> a un <tipo_de_dato> deseado.
Ejemplo: Para cambiar el tipo de dato de los valores resultantes de las siguientes
expresiones:
5 (valor entero)
v (valor entero)
v/h
5/h
5.0 / 2
5 / 2.
5.4 / 2.0
se puede escribir:
( float ) 5
( float ) v
( int ) 5.0
( float ) v / h
( float ) 5 / h
( int ) 5.0 / 2
40
5 / ( int ) 2.
de tal forma que, los resultados de evaluar las expresiones anteriores son:
5 (valor entero)
41
Conversiones implcitas
En los tipos numricos integrados, puede realizarse una conversin implcita
cuando el valor que se va a almacenar puede ajustarse a la variable sin necesidad
de truncamiento o redondeo. Por ejemplo, una variable de tipo long (entero de 8
bytes) puede almacenar cualquier valor que pueda almacenar a su vez un
elemento int (4 bytes en un equipo de 32 bits). En el ejemplo siguiente, el
compilador convierte implcitamente el valor de la derecha en un tipo long antes
de asignarlo a bigNum.
C#
// Implicit conversion. num long can
// hold any value an int can hold, and more!
int num = 2147483647;
long bigNum = num;
En los tipos de referencia, siempre existe una conversin implcita desde una
clase a cualquiera de sus interfaces o clases base, directas o indirectas. No se
requiere una sintaxis especial, ya que una clase derivada siempre contiene todos
los miembros de una clase base.
Derived d = new Derived ();
Base b = d; // Always OK.
Conversiones explcitas
Sin embargo, si no se puede realizar una conversin sin riesgo de perder
informacin, el compilador requiere que se realice una conversin explcita,
denominada conversin de tipo. Una conversin de tipo es una manera de
informar al compilador de forma explcita de que pretende realizar la conversin y
que est al tanto de que puede producirse una prdida de datos. Para realizar
una conversin de tipo, especifique entre parntesis el tipo al que se va a aplicar
dicha conversin delante del valor o la variable que se va a convertir. El programa
siguiente convierte un tipo double a un tipo int. El programa no se compilar sin el
operador de conversin de tipo.
C#
class Test
{
static void Main()
{
double x = 1234.7;
int a;
// Cast double to int.
a = (int)x;
System.Console.WriteLine(a);
}
}
// Output: 1234
42
En los tipos de referencia, se requiere una conversin explcita si debe convertir
de un tipo base a un tipo derivado:
C#
// Create a new derived type.
Giraffe g = new Giraffe();
using System;
class Animal
{
public void Eat() { Console.WriteLine("Eating."); }
public override string ToString()
{
return "I am an animal.";
}
}
class Reptile : Animal { }
class Mammal : Animal { }
class UnSafeCast
{
43
static void Main()
{
Test(new Mammal());
44
Actividad 5.
Agregar acciones semnticas a la estructura de la gramtica.
Obsrvese que, en general, para poder aplicar un esquema de traduccin hay que
construir el rbol sintctico y despus aplicar las acciones empotradas en las
reglas en el orden de recorrido primero-profundo. Por supuesto, si la gramtica es
ambigua una frase podra tener dos rboles y la ejecucin de las acciones para
ellos podra dar lugar a diferentes resultados. Si se quiere evitar la multiplicidad de
resultados (interpretaciones semnticas) es necesario precisar de que rbol
sintctico concreto se esta hablando.
45
estamos hablando. Cuando hablemos del atributo de un nodo utilizaremos una
indexacin tipo hash. Aqu VAL es un atributo de los nodos de tipo
denotando su valor numrico y para accederlo escribiremos $NUM{VAL}.
Anlogamente $expr{TRA} denota el atributo ``traduccin'' de los nodos de
tipo .
Un atributo tal que su valor en un nodo puede ser computado en trminos de los
atributos de los hijos del nodo se dice que es un atributo sintetizado.
Un atributo heredado es aquel cuyo valor se computa a partir de los valores de sus
hermanos y de su padre.
package tokens;
import java.util.*;
/**
*
* @author Invitado
46
*/
public class Tokens {
static String linea = "38+2*3";
//usando delimitadores y regresandolos como tokens
static StringTokenizer tokens3 = new StringTokenizer(linea, "+-*/=", true);
static final int NUMERO=0;
static final int OPERADOR=1;
static String lexema="";
47
while(tokens.hasMoreTokens())
System.out.println(tokens.nextToken());
System.out.println();
//usando delimitadores
StringTokenizer tokens2 = new StringTokenizer(linea, "+=");
while(tokens2.hasMoreTokens())
System.out.println(tokens2.nextToken().trim());
System.out.println();
*/
int token=lexico();
do
{
System.out.println(token+" "+lexema);
token=lexico();
}
while (!lexema.equals(""));
}
}
Resultados del programa ejecutado muestra los tokens utilizados en este mismo
cdigo.
48
Ejemplo 2:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package tabla.de.tokens;
import java.util.*;
/**
*
* @author Invitado
*/
public class TablaDeTokens {
49
}
public String getLexema()
{
return this.lexema;
}
public static final int p=23; // el tamao del arreglo de hash (un nmero primo)
50
listaLigada[i] = new LinkedList<ElementoTs>(); /* inicializamos el arreglo de
listas ligadas*/
51
ts.put ("xVar", s);
Ejecucin de una accin semntica del programa que busca y analiza Tokens en
su cdigo fuente
Ejemplo 3:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace analizador_lexico
{
classRegexLexer
{
Regex rex;
StringBuilder patron;
bool requiereCompilar;
List<string> TNames;
int[] GNumbers;
public RegexLexer()
{
52
requiereCompilar = true;
TNames = newList<string>();
}
///<summary>
/// Agrega una nueva regla para reconocer token
///</summary>
//"/[*].*?[*]/", "COMENTARIO2"
///<param name="pattern">patrn en el que debe encajar</param>
///<param name="token_name">id nico para este patrn</param>
///<param name="ignore">true para no devolver este token</param>
publicvoid AddTokenRule(string pattern, string token_name, bool ignore = false)
{
if (string.IsNullOrWhiteSpace(token_name))
thrownewArgumentException(string.Format("{0} no es un nombre vlido.", token_name));
if (string.IsNullOrEmpty(pattern))
thrownewArgumentException(string.Format("El patrn {0} no es vlido.", pattern));
if (patron == null)
patron = newStringBuilder(string.Format("(?<{0}>{1})", token_name, pattern));
else
patron.Append(string.Format("|(?<{0}>{1})", token_name, pattern));
if (!ignore)
TNames.Add(token_name);
requiereCompilar = true;
}
///<summary>
/// Reinicia el Lexer
///</summary>
publicvoid Reset()
{
rex = null;
patron = null;
requiereCompilar = true;
TNames.Clear();
GNumbers = null;
}
///<summary>
/// Analisa una entrada en busca de tokens validos y errores
///</summary>
///<param name="text">entrada a analizar</param>
publicIEnumerable<Token> GetTokens(string text)
{
if (requiereCompilar) thrownewException("Compilacin Requerida, llame al mtodo
Compile(options).");
if (!match.Success) yieldbreak;
while (match.Success)
53
{
if (match.Index > index)
{
string token = text.Substring(index, match.Index - index);
break;
}
}
///<summary>
/// Crea el AFN con los patrones establecidos
///</summary>
publicvoid Compile(RegexOptions options)
{
if (patron == null) thrownewException("Agrege uno o ms patrones, llame al mtodo
AddTokenRule(pattern, token_name).");
if (requiereCompilar)
{
try
{
rex = newRegex(patron.ToString(), options);
GNumbers = newint[TNames.Count];
string[] gn = rex.GetGroupNames();
54
requiereCompilar = false;
}
catch (Exception ex) { throw ex; }
}
}
///<summary>
/// Cuenta la cantidad de lineas presentes en un token, establece el inicio de linea.
///</summary>
privateint CountNewLines(string token, int index, refint line_start)
{
int line = 0;
for (int i = 0; i < token.Length; i++)
if (token[i] == '\n')
{
line++;
line_start = index + i + 1;
}
return line;
}
}
}
55
Actividad 6.
Manipular la tabla de conversin de smbolos y de errores y direcciones.
56
chequeo semntico. Aunque esta informacin puede extraerse de la estructura de
tipos, para un control ms eficiente, se puede indicar explcitamente.
57
Vamos a hacer un intrprete. Recordar que en un intrprete la entrada es un
programa y la salida es la ejecucin de ese programa.
58
Si ejecutramos ahora la instruccin: a = a + b
Tendramos a a y b en la tabla de smbolos con lo cual solo tendramos que
modificar el valor de a.
Como hemos dicho una tabla de smbolos es una estructura que almacena
informacin relativa a los identificadores de usuario. Pero, Qu informacin
exactamente?, segn el propsito que tengamos. En nuestro caso el propsito es
hacer un intrprete y nos interesa mantener informacin, entre otras cosas, del
valor de cada variable.
Ejemplo 1:
package tablasimbolos;
import java.util.*;
public static final int p=23; // el tamao del arreglo de hash (un nmero primo)
59
public static int h(String x) // la funcion de hash
{ int suma=0;
for (int i=0; i<x.length(); i++)
suma+=x.charAt(i);
return suma%p;
}
public static void main(String args[])
{
60
System.out.println("Lo encontro: " + elemento.getLexema()+" estaba en la
lista "+buscar);
bandera=true;
}
if(bandera == false)
{
System.out.print("No Se Encontro elemento: ");
System.out.println(lexema01);
bandera=true;
}
Ejemplo 2:
package tablasimbolos;
import java.util.*;
61
{
this.lexema=l;
}
public String getLexema()
{
return this.lexema;
}
public static final int p=23; // el tamao del arreglo de hash (un nmero primo)
if(bandera == false)
{
System.out.print("No Se Encontro elemento: ");
System.out.println(lexema01);
bandera=true;
}
Ejemplo 3:
package tablasimbolos;
import java.util.*;
63
String lexema; //aqui debemos poner todos los atributos que
queremos usar en el compilador
int longitudBytes;
public ElementoTs(String l) // constructor que recibe lexema
{
this.lexema=l;
}
public void setLexema(String l) // a partir de aqui ponemos todos los
"getters" y los "setters"
{
this.lexema=l;
}
public String getLexema()
{
return this.lexema;
}
public static final int p=23; // el tamao del arreglo de hash (un nmero primo)
64
// lexema=Entrada.nextLine();
65
Actividad 7.
Integrar equipos de trabajo para la construccin de un analizador
semntico.
66
Actividad 8.
Propuesta de proyecto para el analizador lxico y sintctico.
Objetivos:
Intrpretes y Compiladores:
67
muy pocos nos sentamos a tratar de entender su mecnica, su funcionamiento y
ver los conceptos que estn ocultos detrs de ellos.
Digo ocultos porque es de mi conocimiento, que estos conceptos son tales, que
no se me hubieran ocurrido que forman parte de la teora que engloba a los
Interpretes y Compiladores. Los principios y tcnicas de escritura de Interpretes y
Compiladores comprende los conceptos de: los lenguajes de programacin, la
arquitectura de computadores, la teora de lenguajes, los algoritmos, la ingeniera
de Software, como as tambin tener pleno conocimiento de las distintas
plataformas existentes, de las tcnicas de programacin ( lineales, estructuradas,
orientadas a objetos, a eventos y paralelas ), y de los distintos Hardware, tanto
desde el punto de vista de un programador como al nivel en que interactan sus
componentes internos, para poder obtener de ellos la mayores prestaciones
posibles. Adems, el tener conocimiento de lo que es una maquina abstracta, su
relacin con la gramtica y muchos otros conceptos.
Hay que destacar que el estudio terico que aqu se realizara, es una importante
base para la investigacin y desarrollo de aplicaciones en las cuales el anlisis de
patrones este muy vinculadas con ellas, como por ejemplo Bases de Datos,
Desarrollo de herramientas Orientadas a Objetos, Graficadores, Procesadores de
Texto, Formatos de Archivos, Traductores, Analizadores Lxicos, Analizadores
Sintcticos, por supuesto Interpretes y Compiladores y muchas otras
aplicaciones. Adems, haciendo uso de los conceptos de la Teora General de
Sistemas y los de una maquina abstracta, en particular las denominada Autmatas
Traductores, se puede llegar a la implementacin de un sistema como un
autmata, que ante la lectura de patrones (entrada de datos) reacciona con una
traduccin (salida de datos). Es por todo esto y por una curiosidad propia que he
decido realizar este proyecto.
Planificacin de Actividades:
Objetivos:
Primera etapa:
68
_Observar la dualidad y correspondencia entre una Gramticas Regular y un
Autmata Finito.
Segunda etapa:
Tercera etapa:
Cuarta etapa:
69
Quinta etapa:
70
Conclusiones
71
Bibliografa
Ceballos, F. J. (2007). Enciclopdia de Microsoft Visual C#. 2da Edicion. Espaa:
Ra-MA.
Hopcroft, J. E. (2007). Teoria de automatas, Lenguajes y Computacion . Madrid,
Espaa: PERSON .
http://www.gramaticas.net/2012/05/ejemplos-de-analisis-semantico.html
http://cidecame.uaeh.edu.mx/lcc/mapa/PROYECTO/libro32/autocontenido/autoc
on/45__errores_semnticos.html
http://cidecame.uaeh.edu.mx/lcc/mapa/PROYECTO/libro32/autocontenido/autoc
on/311_manejo_de_los_errores_sintcticos.html
CRISTIAN GUILLERMO GARCA. (2012). Operadores. 2014, de Universidad
Distrital francisco Jos de Caldas Sitio web: http://profesores.fi-
b.unam.mx/carlos/lcpi/p09/OPERADORES%20EN%20%20C++.pdf
Jess Vegas. (2012). Identificadores, Operadores y Expresiones. 2015, de Dpto.
Informtica Universidad de Valladolid Sitio web:
http://www.infor.uva.es/~jvegas/cursos/prog/tema3.html
72