viernes, 9 de noviembre de 2007

Principios de diseño de lenguajes

2 Principios de diseño de lenguajes
Objetivo: El alumno describirá los procedimientos y gramáticas empleadas en el diseño de los lenguajes de programación.
Contenido:
· Los lenguajes en la estructura y operación de una computadora
· Computadoras virtuales
· Sintaxis
· Semántica básica
· Paradigmas de lenguajes

NOTA: INFORMACION OBTENIDA DEL LIBRO: LENGUAJES DE PROGRAMACION, KENNETH C. LOUDEN.


SINTAXIS

La sintaxis es la estructura de un lenguaje. En los primeros días de los lenguajes de programación, tanto la sintaxis como la semántica de un lenguaje se describían mediante largas explicaciones en inglés y con muchos ejemplos. Aunque la semántica sigue describiéndose de un sistema formal para describir la sintaxis, mismo que ahora esta en uso casi de manera universal. En los años cincuenta Noam Chomski desarrolló la idea de gramáticas libre de contexto, y John Backus, con contribuciones de Peter Naur, desarrolló un sistema notacional para la descripción de gramáticas y se utilizó por primera vez para describir la sintaxis del Algol60. Estas formas Backus Naur –BNF- se han utilizado de manera subsecuente en la definición de muchos lenguajes de programación, incluyendo a Java y Ada.



ESTRUCTURA LÉXICA DE LOS LENGUAJES DE PROGRAMACIÓN.

La estructura léxica es la estructura de sus palabras o tokens. La estructura léxica puede estudiarse por separado de la estructura sintáctica, pero está relacionada íntimamente, puede en algunos casos formar una parte no separable de la sintaxis. Típicamente, la fase de análisis léxico de un traductor reúne en forma de tokens secuencias de caracteres del programa de entrada, los cuales posteriormente se procesan mediante una fase de análisis sintáctico, lo que determina la estructura sintáctica.

Las clases típicas de tokens son las siguientes:
· Palabras reservadas.
· Literales o constantes.
· Símbolos especiales.
· Identificadores.

Se llaman palabras reservadas porque un identificador no puede tener la misma cadena de caracteres que una palabra reservada.

A veces puede crearse un confusión en un lenguaje entre las palabras reservadas y los identificadores predefinidos, es decir, aquellos a los cuales se les ha dado una interpretación inicial para todos los programas en el lenguaje, pero que pueden ser capaces de redefinición (en ocasiones a estos identificadores también se les conoce como palabras clave).

Ahora bien el uso del principio de la subcadena de mayor longitud como una regla estándar en la determinación de los tokens (conocida a veces como el principio de “trozo máximo”): en cada punto se reúne en un solo token la cadena más larga posible de caracteres.
El formato de un programa puede afectar la forma en la que se reconocen los tokens. Por ejemplo, el principio de la subcadena más larga requiere que ciertos tokens queden separados mediante delimitadores de token o espacio en blanco. El final de una línea o renglón de texto puede tener un significado doble. Puede ser un espacio en blanco y también pude significar el fin de una identidad estructural.

Los tokens en un lenguaje de programación se pueden describir formalmente mediante expresiones regulares, que son descripciones de patrones de caracteres. Las expresiones normales tienen tres operaciones básicas: concatenación, repetición y elección o selección. Se indica la repetición mediante el uso de un asterisco después del elemento a repetir; se indica la repetición mediante una barra vertical entre los elemento de los cuales debe efectuarse una selección, y se da la concatenación simplemente al poner en secuencia los elementos sin una operación explícita. A menudo también se incluyen paréntesis para permitir el agrupamiento de operaciones.

La notación de expresiones regulares se amplía mediante operaciones adicionales y caracteres especiales para facilitar su escritura. Por ejemplo, los paréntesis cuadrados con un guión indican un rango de caracteres, + indica una o más repeticiones, indica un elemento opcional y el punto indica cualquier carácter.




GRAMÁTICAS LIBRES DE CONTEXTO Y BNF

Iniciamos nuestra descripción de gramáticas y de BNF con el ejemplo:
(1) oración à frase-sustantiva frase-verbal
(2) frase sustantiva à artículo sustantivo
(3) artículo à a the
(4) sustantivo à girl dog
(5) frase verbal à verbo grase-sustantiva
(6) verbo à sees pets

Una gramática libre de contexto consiste en una serie de reglas gramaticales como se describen a continuación: las reglas están formadas de un lado izquierdo que es un solo nombre de estructura y a continuación el metasímbolo “à”, seguido de n lado derecho formado por una secuencia de elementos que pueden ser símbolos u otros nombres de estructura. Los nombres de las estructuras (por ejemplo, oración) se conocen como no terminales, ya que se subdividen en estructuras adicionales. A las palabras o símbolos de token también se les conoce como terminales, dado que jamás se subdividen. Las reglas gramaticales también se llaman producciones, puesto que producen las cadenas del lenguaje utilizando únicamente los metasímbolos “à” y “” (algunas veces se permiten paréntesis para agrupar cosas).
Una gramática libre de contexto también tiene un no terminal distinguido, conocido como símbolo inicial, este no terminal representa toda la estructura que se está definiendo (como una oración o un programa) y es el símbolo con el que se inician todas las derivaciones. Un leguaje libre de contexto define un lenguaje conocido como el lenguaje de la gramática. Este lenguaje es el conjunto de todas las cadenas de terminales para las cuales existe una derivación que empieza con el símbolo de inicio y termina con la cadena de terminales.

En una gramática libre de contexto típicamente existen tantas producciones como no terminales, aunque uno podría eliminar el metasímbolo “” escribiendo cada opción por separado.

Los teóricos de los lenguajes formales han estudiado extensamente las gramáticas libre al contexto y éstas ahora se han comprendido tan bien que es natural expresar la sintaxis de cualquier lenguaje de programación en formato BNF. Ciertamente, al hacerlo se facilita la escritura de traductores para el lenguaje, ya que la etapa de análisis gramatical se puede automatizar.





ÁRBOLES DE ANÁLISIS SINTÁCTICO Y ÁRBOLES DE SINTAXIS ABSTRACTA

La sintaxis establece una estructura, no un significado. Pero el significado de una oración (o de un programa) tiene que estar relacionado con su sintaxis. En inglés una oración tiene sujeto y predicado (“la acción”) determinan el significado de la oración. El sujeto generalmente se presenta al principio de una oración y está dado por una frase sustantiva. El sujeto generalmente se presenta al principio de una oración y está dado por una frase sustantiva. Entonces, en la sintaxis de una oración en inglés, una frase sustantiva se coloca primero y subsecuentemente es asociada con un sujeto. Ocurre lo mismo, en la gramática para las expresiones, cuando escribimos esperamos añadir los valores de las dos expresiones del lado derecho para obtener el valor de la que se encuentra del lado izquierdo. Este proceso de asignar la semántica de construcción a su estructura sintáctica se conoce como semántica dirigida por la sintaxis. Por lo tanto, debemos construir la sintaxis de manera que refleje tanto como sea posible la semántica que eventualmente le daremos (la semántica dirigida por la sintaxis también podría, con igual facilidad, haberse llamado sintaxis dirigida de la gramática).
Para utilizar la estructura sintáctica de un programa que determine su semántica, debemos tener alguna forma de expresar esta estructura tal y como se determina mediante una derivación. El método estándar para ello es mediante un árbol de análisis sintáctico. Éste describe de manera gráfica el proceso de reemplazo dentro de una derivación.


LOS LENGUAJES EN LA ESTRUCTURA Y OPERACIÓN DE UNA COMPUTADORA.

En sus inicios los lenguajes de programación imitaron y abstrajeron las operaciones de una computadora. No resulta sorprendente que el tipo de computadora para la cual fueron escritos tuviera un efecto significativo sobre su diseño. En la mayoría de los casos, la computadora en cuestión fue el modelo Von Neumann: una unidad de procesamiento central única que, en forma secuencial, ejecuta instrucciones que operan sobre valores almacenados en la memoria.

Un lenguaje caracterizado por estas propiedades – la ejecución secuencial de instrucciones, el uso de variables en representación de localizaciones de memoria y el uso de la asignación para cambiar el valor de las variables- se conoce como lenguaje imperativo, puesto que su característica principal es una secuencia de enunciados que representan comandos, es decir órdenes. Algunas veces a este tipo de lenguaje se les llama también procedurales.

La mayoría de los lenguajes de programación actuales son imperativos. Pero no es necesario que un lenguaje de programación describa la computación de esta manera. De hecho, el requisito de que la computación sea descrita como una secuencia de instrucciones, cada una de ellas opera sobre una sola pieza de datos, se conoce como el cuello de Von Neumann, dado que limita la capacidad de un lenguaje de indicar computación en paralelo, es decir, computación que se puede aplicar a muchas piezas de datos simultáneamente y la computación no determinística, o computación que no depende del orden.

El reto del diseño del lenguaje de programación es lograr la potencia, expresividad y comprensión que requiere la legibilidad del ser humano, mientras se conservan al mismo tiempo la precisión y simplicidad necesarias para la traducción de máquina. La legibilidad del ser humano es un requisito complejo y sutil. Depende en gran parte de las capacidades que tiene un lenguaje de programación para la abstracción.

Un lenguaje exitoso de programación tiene utilerías para la expresión natural de la estructura de datos (abstracción de datos) y para la estructura del proceso computacional para la solución de un problema (abstracción de control).

El diseño de los lenguajes es una de las áreas más difíciles y menos comprendidas de la ciencia de la computación. En los párrafos anteriores se hace énfasis en la legibilidad del ser humano, así como en los mecanismos para el control de la abstracción y de la complejidad como requisitos clave en un lenguaje en un lenguaje de programación moderno. Sin embargo, es difícil juzgar un lenguaje basándonos en estos criterios, ya que el éxito o fracaso de un lenguaje puede depender de las interacciones complejas entre los mecanismos del mismo.


MAQUINAS VIRTUALES.
Una máquina virtual es un sistema operativo que funciona de forma "simulada", es decir, es como tener un ordenador dentro de tu ordenador, pero funcionando de forma "virtual", es decir, en realidad no tienes un ordenador dentro de tu ordenador, ya que eso es imposible, pero lo que hacen los programas como los que te he mencionado antes es simular que tienes otro ordenador funcionando dentro del tuyo.
En realidad las máquinas virtuales son eso: simulaciones de otros ordenadores pero en modo "soft", es decir, el programa simula que tiene una bios, una memoria, unas conexiones de red, puertos, discos duros, etc., pero todo de forma "simulada".
Y lo bueno que tienen esas máquinas virtuales es que puedes instalar cualquier sistema operativo en ellas, incluso sistemas operativos diferentes al sistema operativo real, por ejemplo, supongamos que tenemos un Windows XP, dentro de ese XP podemos tener desde un Linux hasta un Windows 2003 Server pasando por un Windows Vista.
Lo bueno de tener o usar máquinas virtuales es que en realidad no es necesario que tengas más discos duros ni más CD o DVD, ya que todo es "simulado", puedes crear discos duros virtuales que en realidad son también "simulados", ya que en realidad son ficheros que el programa crea y en el que instala todo lo que quieras instalar.
Además de los discos simulados (o virtuales), también puedes usar cosas que ya tienes en tu equipo, por ejemplo, un CD o un DVD, la impresora, otro disco duro "real", etc.
Pero también puedes "simular" cosas que no tienes, por ejemplo una disquetera o incluso un CD o DVD, esto es útil cuando quieres probar cosas que necesitan de esa disquetera que ya casi nadie usa.
Y la ventaja de usar los CD o DVD simulados es que puedes trabajar con "imágenes" como si fueran discos compactos reales. Esas imágenes son las que los propios programas de grabación crean, y que suelen tener extensiones como .iso o .img.

VENTAJAS DE LAS MÁQUINAS VIRTUALES
Como ves, con las máquinas virtuales podemos tener varios sistemas operativos sin necesidad de crear particiones o tener más discos duros, esto nos permitirá poder tener sistemas operativos para pruebas.
Por ejemplo, que sale una versión beta y no queremos instalarla en nuestro sistema operativo de trabajo, ya que las betas son eso, "pruebas" y puede que nos deje el sistema operativo inestable, algo que no querremos con nuestro equipo de trabajo.


PARADIGMAS DE LENGUAJE

Paradigmas es una palabra derivada de las griegas “ejemplo” y “mostrar”, que significa “un ejemplo que sirve como norma (DRAE)
Un paradigma de programación es un modelo básico para el diseño y la implementación de programas. Un modelo que con unas normas especificas como: estructura modular, alta reusabilidad, fuerte cohesión, etc. Determina el proceso de diseño y la estructura final de un programa.
La mayoría de los paradigmas están familiarizados con el paradigma mas difundido, el de la programación procedimental, cuya característica fundamental es la secuencia de acciones realizadas paso a paso.
Sin embargo existe una gran variedad de ellos en razón de alguna particularidad metodología o funcional por ejemplo:

· Programación lógica
· Programación heurística
· Paradigma basados en el flujo de datos
· Paradigmas procedimentales
· Paradigma orientado a objetos
· Paradigma funcional




SEMANTICA BASICA

La especificación de la semántica (o significado) de un lenguaje de programación es una tarea más difícil que la especificación de su sintaxis, existen varias formas de especificar la semántica:

· Manual de referencia de lenguaje: el cual es el método mas común, un ejemplo de ello son los manuales tradicionales, aunque a veces sufren de ambigüedades.
· Traductor definidor: su ventaja es que las preguntas a cerca de un lenguaje pueden ser resueltas con un experimento
· Definición formal: se realiza mediante métodos matemáticos, pero pueden resultar complejos y requieren un nivel de estudio.
EJEMPLO:
“… del enunciado if de C, su semántica puede ser descrita en palabras de la siguiente forma (adaptado de kernighan y richie [1988];
Un enunciado if es ejecutado, primero, evaluando su expresión, misma que debe tener tipo aritmético o apuntador, incluyendo todos los efectos colaterales, y se compara diferente de 0, el enunciado que sigue a la expresión es ejecutado. Si existe una parte else, y al expresión es 0, el enunciado que sigue al “else” es ejecutado.” 1



1. lenguajes de programaron, 1.4 Definición de lenguaje, kenneth C. Louden, pag19.