El principal objetivo del lenguaje
es, por supuesto, servir de apoyo didáctico en una materia de lenguajes de
programación, intérpretes y compiladores. Derivado de la persecución de este
objetivo surgen varias metas específicas y objetivos particulares:
En el diseño de Stop se ha tratado
de seguir muchos de los principios usados en los modernos lenguajes de
programación hasta el punto donde su implementación no sea demasiado complicada
para el desarrollo de un proyecto semestral. Principalmente se ha buscado que
sea regular, modular y estructurado.
El lenguaje de programación esta
pensado para la programación evolutiva. Esta consiste en un método de
programación basado en un ciclo de prueba y error donde se refina un programa
hasta conseguir que haga lo que queremos. Esta forma de programar se aplica a
problemas donde se desconoce que algoritmo nos llevará a la solución. Esta
situación se da en investigación y en la creación de prototipos donde hay que
realizar muchas pruebas hasta dar con la solución más apropiada. Para estos
casos, es más apropiado el uso de un interprete que un compilador, ya que de
esta forma se reduce el tiempo invertido en cada prueba.
Para que un lenguaje sea efectivo en
programación evolutiva tiene que facilitar: la interacción, la modificación del
programa y aportar instrucciones de alto nivel cercanas al problema. Estos tres
punto se consiguen cuando el lenguaje tiene las siguientes características:
Estado
de Interacción. Entre prueba y prueba es
interesante guardar el estado de ejecución. De esta forma se evita repetir la
ejecución de las instrucciones necesarias para llegar al estado de ejecución
donde queremos realizar pruebas. Los programas implementa esta característica
mediante un ámbito global dinámico que guarda funciones y variables mientras se
utiliza el intérprete.
Sintaxis
Cercana al Problema. Es más efectivo escribir en una
notación cercana al problema que adaptarse a la sintaxis de un lenguaje de
programación. De esta forma se evita el paso de traducción que tiene que
realizar el programador antes de escribir una nueva sentencia del programa.
Abstracción. La semántica del lenguaje tiene que ser cercana a la semántica
de la notación utilizada en el problema. Como no es cuestión de construir un
lenguaje para cada problema, lo que se hace es aportar herramientas para
acercar la semántica del lenguaje a la del problema mediante abstracción.
Integración. Para la mayoría de campos se encuentran librerías que
implementan las operaciones más comunes. Entonces para que un lenguaje sea
efectivo tiene que poder integrar estas librerías.
Fácil
Escritura. En la programación estándar es más importante
facilitar la lectura de programas que la escritura (se leen más veces que se
escriben). En el caso de lenguajes interactivos es importante que la escritura
de sentencias sea fácil.
Concisión. Las sentencias ha escribir tienen que ser cortas para agilizar
la interacción. aporta generadores, listas por comprensión y una mínima
redundancia para reducir el tamaño de los programas sin perder en claridad.
Modificación
Local. La evolución de un programa se consigue por sucesivas
modificaciones que se han de poder realizar rápidamente. Esto se consigue si
las modificaciones del programa afectan al menor código posible. Esto supone
que la modificación se realizará solo en un lugar del programa y no en dos como
se da el C++ donde hay que modificar el fichero de implementación (.cpp) y el
fichero de cabecera (.h).
Hasta
el momento, lo que se ha visto ha sido una serie de operaciones aritméticas y
de manipulación de la pila. Todas éstas indicadas de manera implícita a través
de una serie de términos y convenciones que es necesario definir de forma más
precisa antes de continuar con otra cosa.
Existen
dos formas en las que puede representarse una pila y su funcionamiento; de ésta
dependerá la terminología que se emplee. Nosotros hemos venido usando una
representación que conceptualiza a la pila como un arreglo que
"crece" o es utilizado desde su base (el primer nivel) hacia arriba.
Los datos entran y se toman de la base y desplazan o "empujan" a los
elementos, que ya pudieran estar introducidos en la pila, hacia arriba.
Identificaremos a los diversos elementos involucrados acorde al siguiente
diagrama:
Niveles |
|
... |
^ |
||||||||
|
|
||||||||||
|
|
^ |
|
Llamaremos
nivel a cada una de las localidades con que cuente la pila y los enumeraremos a
partir de 1. La base es el primer nivel. El tope de la pila lo identificaremos
como el nivel en el que se encuentre el elemento con ingreso más antiguo.
Representaremos con una elipsis (...) el resto de las localidades o elementos
en la pila. Por último, mientras que nos hemos limitado a usar números en la
representación de elementos que pueden ser introducidos en la pila, no estamos
restringidos a esto. Dependiendo de su implementación una pila puede albergar
más que números. De forma genérica nos referiremos a estos elementos como
objetos.
Los
diagramas que se han usado para ilustrar el contenido de la pila antes y
después de la aplicación de una instrucción (que aparece como una operación,
función, operador o nombre en el código del programa) serán identificados como
diagramas de pila. En estos diagramas la elipsis se incluirá sólo cuando sea
necesario recalcar la existencia del resto de la pila o su contenido; mientras
no se indique lo contrario, siempre debe considerarse a la pila de Stop como
infinita y factible de tener un contenido.
Adicionalmente,
en la presente descripción:
Las palabras
clave de Stop se escriben en mayúsculas, aunque el lenguaje no es sensible a
altas o bajas (lo que en otros ambientes es lo que se denomina case
insensitive). Palabras clave de Stop se escriben usando un font no
proporcional.
·
Elementos a substituir por otro valor se ilustran en itálicas.
·
Conceptos y acciones a resaltar se subrayan.
·
En las descripciones sintácticas, elementos repetitivos se
denotan por el seguimiento de una
elipsis.
·
Salidas en pantalla se muestran en negritas.
Las teorías de la
comunicación representan un punto de partida indispensable no sólo para el
estudio y la investigación de la comunicación, sino para el quehacer
profesional práctico. El curso discute las aportaciones conceptuales de las
perspectivas teóricas más recientes para el análisis de la comunicación masiva
contemporánea.
Comunicación interpersonal e
intercultural, así como las habilidades interactivas necesarias para gerentes.
Análisis de las capacidades de transmisión de información de
fibras ópticas, tomando en cuenta los sistemas transmisores, los sistemas
receptores y los requerimientos de acoplamiento óptico. Comportamiento de ondas
electromagnéticas en el interior de las fibras ópticas. Receptores óptimos,
transmisión coherente, amplificación óptica, multicanalización por división de
longitud de onda, redes ópticas, SONET, ATM.
La computadora, a diferencia
de otras herramientas que en general apoyan el esfuerzo físico de los humanos,
fue inventada para facilitar el trabajo intelectual. Si el hombre tiene algún
problema, por ejemplo "sumar dos y dos", el diseñador define el
algoritmo que resuelve el problema, el programador lo codifica en un lenguaje
de programación, el cual la computadora es capaz de "entender", luego
la computadora ejecuta el algorítmo expresado como programa en el lenguaje de
programación en cuestión, y listo. La máquina le entrega al hombre la respuesta
"4", sin que éste tuviera que esforzar sus neuronas.
Un programa se escribe una vez, pero se lee muchas durante su
depuración, documentación y mantenimiento.
Tendencia actual a separar la interfaz de la implementación de
un módulo.
Reducir las manipulaciones implícitas.
Coerciones (coerciones de PL/I o C).
ON de BASIC para eventos o excepciones.
Constructores y destructores de C++ (necesarios, pero complican
el seguimiento del flujo de ejecución).
un conjunto de instrucciones de la máquina
facilitar la compilación (forth).
Evitar incluso la posibilidad de escribirlas
Reducir el conocimiento contextual.
El programador no funciona con una pila como el programa
compilado.
Tener
una serie de defensas tal que si un error no es detectado por uno, este
probablemente sea detectado por otro.
Los
errores deben ser detectados por el
compilador, si un mecanismo no es capaz de detectar un error es necesario
implementar otro que lo detecte, pero nunca ignorarlo.
A continuación se presentan prevencion y tolerancia
de errores y fallos
Prevencion de errores
Ejecutar
datos -> control de flujo limitado
Errores
en el uso de datos -> Tipado fuerte
Apuntadores
erróneos -> Gestión de memoria implícita (LISP, PROLOG, ML, etc).
Hay que facilitar su
detección, identificación y corrección. Tener que declarar antes de utilizar.
Evitar coerciones inductoras de errores.
Prevención y tolerancia de
fallos
Prevención de fallos: Se trata de evitar
que se introduzcan fallos en el sistema antes de que entre en funcionamiento
Prevención de fallos
Se realiza en dos
etapas:
–
Se trata de impedir que se introduzcan fallos durante la
construcción del sistema
–
Consiste en encontrar y eliminar los fallos que se producen en
el sistema una vez construido
Tolerancia de fallos: Se trata de
conseguir que el sistema continúe funcionando aunque se
produzcan fallos
En ambos casos el objetivo es
desarrollar sistemas con modos de fallo bien definidos.
Detección de errores
hardware (p.ej..
instrucción ilegal)
ºnúcleo o sistema
operativo (p.ej. puntero nulo)
Duplicación
(redundancia con dos versiones)
Comprobaciones de
tiempo
Inversión de
funciones
Códigos detectores
de error
Validación de
estado
Validación
estructural
Compilación rápida del código
fuente y ejecución rápida del código objeto.
Los
factores fundamentales en la calidad del software son: la eficiencia, la portabilidad, la verificabilidad, la integridad, la facilidad
de uso, la exactitud, la robustez, la extensibilidad, la compatibilidad y la
reutilización. En términos generales, estos factores pueden describirse de la
siguiente forma:
La eficiencia: capacidad
para el aprovechamiento óptimo de los recursos que emplea.
Los lenguajes OOP arrastraron en un
principio la reputación de ser ineficaces. Esto se debía en gran medida a que
los primeros lenguajes (como Smalltalk) eran interpretados y no compilados. La
existencia de compiladores permite a los desarrolladores ganar rapidez.
Actualmente, usando un buen lenguaje orientado a objetos como C++, Java, etc.
Junto con las librerías apropiadas para la realización de un programa, puede
que se ejecute más rápidamente que el mismo programa compilado con un lenguaje
procedural
La portabilidad: facilidad para ser ejecutados en
distintos entornos lógicos o físicos .
La verificabilidad: capacidad para soportar
procedimientos de pruebas, test o ensayos.
La integridad: nivel de protección frente a procesos que
traten de alterarlo.
La facilidad de uso: comodidad y claridad en la
interacción con el usuario.
La exactitud: nivel de precisión que alcanzan los
resultados obtenidos.
La robustez: capacidad para funcionar correctamente en
situaciones extremas.
La extensibilidad: capacidad para adaptar su
funcionamiento al incremento en sus objetivos.
La compatibilidad: facilidad de poder ser aplicados en
conjunción con otros programas.
La reutilización: posibilidad de utilizarlos (total o
parcialmente) en nuevos contextos.
Independencia de la máquina: Puesto que
diferentes usuarios utilizan diferentes ordenadores, el sistema debe ser
accesible por todos ellos sin merma de prestaciones, especialmente por las
plataformas mayoritarias: Windows, MacOS y Unix.
Los programas Windows son
independientes de la máquina en la que se ejecutan (o al menos deberían serlo),
el acceso a los dispositivos físicos se hace a través de interfaces, y nunca se
accede directamente a ellos. Esta es una de las principales ventajas para el
programador, ya que no hay que preocuparse por el modelo de tarjeta gráfica o
de impresora, la aplicación funcionará con todas, y será el sistema operativo
el que se encargue de que así sea.
A la hora de explotar un gran número de bases de datos de
diferentes editores nos encontramos ante un doble problema. Por una
parte, la citada falta de homogeneidad de los sistemas informáticos de los
usuarios; por otra parte, cada una de las bases de datos suele tener su propio
programa de consulta, de modo que nos encontramos multitud de programas
diferentes que deberán conocer los usuarios. Dichos programas están en su mayor
parte diseñados para ordenadores tipo PC con sistema operativo Windows.
Teniendo en cuenta todo lo anterior, podemos ver que el sistema ha de permitir
acceder a multitud de máquinas diferentes a una serie de programas en muchos
casos incompatibles con ellas.
Los
servidores de aplicaciones son la base de programas informáticos diseñados para
ser ejecutados desde ordenadores personales a través de Navegadores de Internet
convencionales.
Con ello se consigue independencia de la máquina (los programas funcionan en
cualquier ordenador), independencia de ubicación (es posible utilizar los
programas desde cualquier lugar) y una administración ligera y centralizada
(mantenimiento cero de los programas de los ordenadores de los usuarios al
residir éstos en el servidor).
Un lenguaje debe ser tan simple como sea posible. Debe haber un número
mínimo de conceptos con reglas simples para su combinación. Un lenguaje de
programación debe esforzarse en la
simplicidad sintáctica y semántica. Simplicidad en la semántica implica que el
lenguaje contiene un mínimo número de conceptos y estructuras. Estos conceptos
deben ser naturales, rápidamente aprendidos, y fácilmente entendidos. with
little danger of misinterpretation.
La simplicidad requiere que
un idioma incorpore tan pocos conceptos como sean posibles. El lenguaje debe
ser una ayuda para el programador antes de que alcance el estado real de
codificación en programación. Debe darle un conjunto de conceptos claro, simple
y unificado para que pueda usarlos como primarios en el desarrollo de
lenguajes. Para ello es deseable tener un número mínimo de conceptos
diferentes, con las reglas de su combinación lo más simples y regulares
posibles. Esta claridad semántica y de conceptos es el factor determinante del
valor de un lenguaje.
La
simplicidad sintáctica requiere que la sintaxis represente cada concepto en una
y una única forma y que ésta interpretación es tan legible como sea
posible. Esto no necesariamente implica
que la sintaxis es tan concisa como sea posible, desde que la concisión es a
menudo contraproducente a la legibilidad. Excluye múltiples representaciones de
la misma semántica conceptual y representaciones sintácticas que son fácilmente
confusas.
Ya que la representación de los
objetos lleva implica tanto el análisis como el diseño y la codificación de los
mismos.
La estructura lógica de la BD definida mediante el LDD debe ser
uniforme y acorde al modelo de datos del SGBD, para facilitar la manipulación
de esta estructura.
En el caso específico del LDD, el lenguaje del SGBD debe ser
capaz de definir la estructura lógica de la BD, sin entrar en detalles de
implementación ni mecanismos en que se accede a los datos de la BD.
La forma idónea de realizar lo anterior es mediante un lenguaje
declarativo, el cual permite declarar la estructura del modelo de acuerdo al
modelo de datos que utiliza el SGBD.
Para el caso del LMD, el lenguaje del SGBD debe incluir formas
de especificar qué se desea hacer con los datos (insertar, recuperar, modificar
o borrar datos), sin entrar en detalles acerca de cómo se realizan estas
operaciones.
Igual que en el caso anterior, la mejor manera de realizar esto
es mediante un lenguaje declarativo que permita especificar la estructura de la
operación a realizar, de acuerdo siempre con el modelo de datos utilizado por
el SGBD.
Generalización y
especialización
–
La generalización dice que algo similar también es correcto,
pero es difícil de implementar.
–
Hay que especializar para facilitar la implementación sin perder
la utilidad del lenguaje.
(Microestructuras,
estructuras de expresión, estructura de datos, estructuras de control,
estructuras de compilador
y estructuras de
E/S.)
El diseño
detallado tiene que ver con la especificación de detalles algorítmicos,
representaciones concretas de datos, interconexiones entre funciones y
estructuras de datos, y empaque del producto de programación. El diseño
detallado está fuertemente influenciado por el lenguaje de instrumentación,
pero no es lo mismo que la instrumentación; el diseño detallado tiene que ver
más con aspectos semánticos y menos con detalles sintácticos que es la
instrumentación.
El punto de inicio para el diseño detallado es
una estructura arquitectónica a la que se le van a proporcionar los detalles
algorítmicos y las representaciones concretas de datos. Mientras que hay una
fuerte tentación para proceder directamente de la estructura arquitectónica a
la instrumentación, hay varias ventajas que pueden lograrse en el nivel intermedio
de detalle proporcionado por el diseño detallado. La instrumentación comunica
los aspectos de la sintaxis del lenguaje de programación, el estilo de
codificación la documentación interna, y la inserción de pruebas y depuraciones
al código. Las dificultades que se encuentran durante la instrumentación casi
siempre se deben al hecho de que el instrumentador simultáneamente está
realizando análisis, diseño y actividades de codificación mientras intenta
expresar el resultado final en un lenguaje de instrumentación. El diseño
detallado permite el diseño de algoritmos y representaciones de datos en un
nivel más alto de abstracción y notación que el que proporciona el lenguaje de
instrumentación . El diseño detallado separa la actividad
de diseño a bajo nivel de la instrumentación, igual que las actividades de
análisis y diseño aíslan las consideraciones de lo que se desea de la
estructura que logrará los resultados deseados. Una especificación adecuada de
diseño detallado minimiza el número de sorpresas durante la instrumentación del
producto.
Las actividades de diseño detallado inevitablemente exponen
los defectos en la estructura arquitectónica y las modificaciones resultantes
se verán facilitadas por tener menos detalles por manipular que los que estarían
presentes en el lenguaje de instrumentación. El diseño detallado también
proporciona un vehículo para inspecciones de diseño, recorridos estructurados y
la revisión crítica del diseño. Las notaciones para el diseño detallado
incluyen a los diagramas HIPO, el seudocódigo, el inglés estructurado, los
diagramas de flujo estructurados, los diagramas de estructuras de datos, y las
distribuciones físicas para las representaciones de datos. La representación
del diseño detallado puede utilizar palabras clave del lenguaje de
instrumentación para especificar el flujo de control, y proposiciones de
declaración del lenguaje para especificar la representación de datos. El
empaque tiene que ver con la manera en que los datos elementales globales son
compartidos selectivamente entre las unidades del programa, la especificación
de áreas de datos estáticos, el agrupamiento de unidades del programa como
funciones y subrutinas, la especificación de los mecanismos para el paso de
parámetros, las estructuras de archivos y las técnicas para su acceso, y la
estructura de las unidades de compilación y módulos de carga. El diseño
detallado debe llevarse hasta un nivel donde cada proposición en la notación
del diseño resulte en unas cuantas (menos de 10) proposiciones en el lenguaje
de instrumentación. Dadas las especificaciones arquitectónicas y de diseño
detallado, cualquier programador familiar con el lenguaje de instrumentación
debe ser capaz de implantar el producto de la programación.
Las Estructuras de Datos se
pueden definir como la organización de la información que permite un
determinado lenguaje de programación. Cada estructura posee sus propias
características de almacenamiento y recuperación de los datos.
Los Algoritmos constituyen la resolución de problemas computacionales mediante
un lenguaje de programación.
·
Tipos por valor: Son aquellos tipos que contienen los datos, el
valor en si. Se almacenan directamente en el disco duro de la computadora y
cuando trabajamos con ellos, trabajamos directamente con el valor. No requiere
de memoria adicional aparte de la estrictamente necesaria para almacenar el
valor. Estos tipos son implementados por el runtime y aumentan
considerablemente la velocidad.
·
Tipos por referencia: Son aquellos que hacen
referencia a una posición de memoria, están guardados en la pila. Son más
lentos que los tipos por valor y ocupan algo más de memoria, a cambio obtienen
varias ventajas como por ejemplo que pueden contener métodos, polimorfismo…
Las estructuras de
datos que se manejan en el modelo relacional corresponden a los conceptos de
relación, entidad, atributo y dominio, los cuales de introducen aquí
intencionalmente:
Relación.
Por una relación se entiende una colección o grupo de objetos
que tienen en común un conjunto de características o atributos.
Entidad.
Es una unidad de datos en una relación con un conjunto finito de
atributos. Es también conocido como n-ada, a raíz de que consiste de n-valores,
uno por cada atributo.
Atributo.
También llamado característica, cada atributo de una
relación tiene asociado un dominio en el cual toma sus valores.
Dominio.
Es un conjunto de valores que puede tomar un atributo en una
relación.
La notación más
usual para denotar las relaciones en términos de estos conceptos es:
5#5
por
ejemplo
6#6
Y para establecer la conexión entre un atributo y un dominio podemos usar la siguiente notación:
7#7
por ejemplo
8#8
Una forma de
implementar las relaciones en una computadora, es a través de tablas de
valores, de forma que se tienen las siguientes equivalencias: un atributo
corresponde al encabezado de una columna, una n-ada equivale a un
renglón de la tabla y por supuesto una relación equivale a la tabla misma. En
capítulos posteriores, suponiendo natural esta equivalencia de términos, se
utilizarán de forma indistinta.
El desarrollo de un programa viene determinado por el orden en
que aparecen las instrucciones. El lenguaje Perl posee controlar un conjunto de
instrucciones que permiten controlar el desarrollo de un programa. Estas
instrucciones se denominan estructuras de control porque
permiten ejecutar un conjunto de instrucciones cuando se verifica una condición
o ejecutar iterativamente un bloque de instrucciones mientras una expresión sea
válida.
Estructura secuencial
Sentencias simples
Expresión de algún tipo terminada
por el carácter ‘;’
i++;
s = v *
t;
;
Sentencias compuestas o bloques
Conjunto de declaraciones y
sentencias entre llaves {}
{
<declaración>;
...
<sentencia>;
...
}
Operador condicional
expresión1
? expresión2 : expresión3;
Sentencia if
if
(expresión) {
sentencia;
}
if
(expresión) {
sentencia1;
} else
{
sentencia2;
}
if
(expresión1)
sentencia1;
else if
(expresion2)
sentencia2;
else if
(...)
...
else
sentenciaN;
Sentencia
switch
switch (expresión) {
case expr_cte1:
sentencia1;
case
expr_cte2:
sentencia2;
...
case
expr_cteN:
sentenciaN;
default:
sentencia;
}
Estructuras iterativas / repetitivas
Sentencia while
while
(expr) {
sentencia;
}
Sentencia for
for
(expr1; expr2; expr3) {
sentencia;
}
Equivale a: expr1;
while
(expr2) {
sentencia;
expr3;
}
Sentencia do … while
do {
sentencia;
} while
(expresión);
Saltos
break Interrumpe
la ejecución del bucle
continue
Comienza la siguiente iteración del bucle
goto Salto
incondicional
return Finaliza
la ejecución de una función
(suele
utilizarse para devolver un valor)
exit Finaliza
la ejecución del programa
(función
de la biblioteca estándar)
La instrucción last.
La instrucción last
interrumpe la ejecución del bucle actual y se ejecuta la instrucción que sigue
al bloque. El ejemplo siguiente permite interrumpir el bucle while
cuando la variable i toma el valor 3.
$i = 0;
while($i < 6) {
if($i == 3) {
last;
}
$i++;
}
print "el valor de \$i es $i";
Cuando la
instrucción tiene como argumento una etiqueta, la ejecución prosigue en la
línea indicada por la etiqueta.
La instrucción next.
La instrucción next
es idéntica a la instrucción continue en C. Interrumpe la ejecución
del bloque de instrucción actual y prosigue la ejecución en la iteración
siguente. Esta instrucción no interrumpe completamente la ejecución del bucle;
la expresión que controla el bucle se evalúa. Si el resultado de la expresión
es válido, el bucle se ejecuta de nuevo.
Cuando una
instrucción tiene como argumento una etiqueta, la instrucción prosigue en la
línea identificada por la etiqueta y no al principio del bloque.
Seguidamente
veremos un ejemplo de dicha instrucción:
print
"Teclea \"x\" para salir:\n";
print "Si se pulsa la tecla \"s\" no se imprime:\n";
$ristra = "";
while ($ristra ne "x") {
$ristra = ; chop($ristra);
if ($ristra eq "s") {
next;
}
print "Has escrito $ristra\n";
}
print "Salida.\n"
La instrucción until.
La instrucción until
al igual que la instrucción while permite ejecutar un conjunto de
instrucciones un número repetido de veces. Pero al contrario que la la
instrucción while, la intrucción until ejecuta dicho bloque
de instrucciones mientras no se verifique la comprobación. La sintaxis es:
until
(expresión) {
instrucción o bloque de instrucciones;
}
He aquí el ejemplo
anterior pero utilizando la instrucción until.
print
"Teclea \"x\" para salir:\n";
print "Si se pulsa la tecla \"s\" no se imprime:\n";
$ristra = "";
until ($ristra eq "x") {
$ristra = ; chop($ristra);
if ($ristra eq "s") {
next;
}
print "Has escrito $ristra\n";
}
print "Salida.\n"
La instrucción unless.
Esta instrucción
es análoga al if, salvo que permite considerar la no verificación de
la prueba. Su sintaxis es la siguiente:
unless
(expresión) {
instrucción o bloque de intrucciones 1;
}
Para ver mejor el
funcionamiento del unless, modificaremos el ejemplo anterior para
adaptarlo a dicha instrucción.
print
"Teclea \"x\" para salir:\n";
print "Si se pulsa la tecla \"s\" no se imprime:\n";
$ristra = "";
until ($ristra eq "x") {
$ristra = ; chop($ristra);
unless ($ristra eq "s") {
next;
}
print "Has escrito $ristra\n";
}
print "Salida.\n"
Cualquier
compilador debe realizar dos tareas principales: análisis del programa a
compilar y síntesis de un programa en lenguaje maquina que, cuando se
ejecute, realizara correctamente las actividades descritas en el programa
fuente.
Para el estudio de
un compilador, es necesario dividir su trabajo en fases. Cada fase representa
una transformación al código fuente para obtener el código objeto. La siguiente
figura representa los componentes en que se divide un compilador. Las tres
primeras fases realizan la tarea de análisis, y las demás la síntesis.
En cada una de las
fases se utiliza un administrador de la tabla de símbolos y un manejador de
errores.
Análisis Léxico.
En la fase de
análisis léxico se leen los caracteres del programa fuente y se agrupan en
cadenas que representan los componentes léxicos. Cada componente léxico es una
secuencia lógicamente coherente de caracteres relativa a un identificador, una
palabra reservada, un operador o un carácter de puntuación.
A la secuencia de
caracteres que representa un componente léxico se le llama lexema (o con
su nombre en inglés token). En el caso de los identificadores creados
por el programador no solo se genera un componente léxico, sino que se genera
otro lexema en la tabla de símbolos.
Análisis
Sintáctico.
En esta fase, los
componentes léxicos se agrupan en frases gramaticales que el compilador utiliza
para sintetizar la salida.
Análisis
Semántico.
La fase de
análisis semántico se intenta detectar instrucciones que tengan la estructura
sintáctica correcta, pero que no tengan significado para la operación
implicada.
Generación de
código Intermedio.
Algunos
compiladores generan una representación intermedia explícita del programa
fuente, una vez que se han realizado las fases de análisis. Se puede considerar
esta operación intermedia como un subprograma para una máquina abstracta. Esta
representación intermedia debe tener dos propiedades importantes: debe
ser fácil de producir y fácil de traducir al programa objeto.
Optimización de
Código.
En esta fase se
trata de mejorar el código intermedio, de modo que resulte un código de máquina
más rápido de ejecutar.
Generación de
Código.
Esta constituye la
fase final de un compilador. En ella se genera el código objeto que por lo
general consiste en código en lenguaje máquina (código relocalizable) o código
en lenguaje ensamblador.
Administrador de
la tabla de símbolos.
Una tabla de
símbolos es una estructura de datos que contiene un registro por cada
identificador. El registro incluye los campos para los atributos del
identificador.
El administrador
de la tabla de símbolos se encarga de manejar los accesos a la tabla de
símbolos, en cada una de las etapas de compilación de un programa.
Manejador de
errores.
En cada fase del
proceso de compilación es posibles encontrar errores. Es conveniente que el
tratamiento de los errores se haga de manera centralizada a través de un
manejador de errores. De esta forma podrán controlarse más eficientemente los
errores encontrados en cada una de las fases de la compilación de un programa.
Diseño de salida. El diseño de un
sistema de información basado en computadora es diseñar la salida o resultado
que producirá el sistema. Se evoca a la selección de contenido forma y medio
para los informes y el resultado que generará el sistema.
*informes
*contenido
*forma
*medio
*formato
*realce
2. Diseño de entrada. Se seleccionan los
registros de entrada y los métodos de tal manera que conozcamos cuales son los
datos que se van a proporcionar cada vez que corra una aplicación en la
computadora.
*registros
*medio
*modo
*volumen
3. Diseño de procesamiento. Se especifica él
computo, manejo de datos y la lógica necesarios para producir el resultado.
*cálculos
*lógica
*frecuencia
*volumen
4. Especificación de
datos. Se especifican los datos algunos se marcarán para que se
almacenen en los archivos maestros, y otros datos que serán de entrada cada vez
que se corra una aplicación.
*contenido del registro.
*diseño del registro
*especificación de los archivos.
*organización de los archivos.
*volumen
5. Especificación de procedimientos. Se desarrollan
los programas y el software de computadora así como los archivos y la
elaboración de bases de datos. 3
*corridas de computadora
*documentar el proceso
*métodos de control
*procesos manuales
*procedimientos operativos. 3
Tiene 5 etapas fundamentales.
Especificación de procedimientos es donde vamos a recopilar toda nuestra información, identificar el o los problemas es necesario tomar en cuenta la factibilidad de nuestro diseño.
Especificación de datos. aquí es donde tenemos que tomar en
cuenta los datos que vamos a utilizar de que tipo son, se diseñara el registro,
los archivos.
Diseño de procesamiento. Una vez que ya sabemos los datos que
habrán que utilizarse se tendrá que saber la frecuencia de estos datos y en
donde se utilizarán, que cálculos habrá de hacerse para que funcione nuestro
sistema para poder elegir un lenguaje de programación adecuado para que de el
resultado requerido.
Diseño de entrad. Una vez que se sabe que lenguaje se utilizara
entonces empezamos a programar cuidando que los datos e intrusiones den como
resultado en la pantalla del usuario la información que este desea.
Diseño de salida. Es el resultado final, se realizan las pruebas
para corroborar que nuestro sistema funcione adecuadamente para poderlo
implantar.