Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Aunque existen muchos lenguajes de programación, las diferencias entre ellos son insignificantes
comparadas con las diferencias entre los lenguajes naturales. En este capítulo, discutiremos los
aspectos comunes compartidos entre los diferentes lenguajes de programación. Estos aspectos
incluyen:
° las estructuras léxicas, sintácticas y semánticas de los lenguajes de programación, los datos y los
tipos de datos, el procesamiento y el preprocesamiento de los programas, y los ciclos de vida del
desarrollo de programas.
° una visión general de los diferentes lenguajes de programación y los conocimientos previos de
estos lenguajes;
El capítulo está organizado como sigue. La sección 1.1 presenta los paradigmas de programación,
el rendimiento características, y el desarrollo de los lenguajes de programación. La sección 1.2
esboza las estructuras y los problemas de diseño de los lenguajes de programación. La sección 1.3
discute los sistemas de tipado, incluyendo los tipos de variables la equivalencia de tipos, la
conversión de tipos y la comprobación de tipos durante la compilación. La sección 1.4 presenta el
preprocesamiento y procesamiento de los lenguajes de programación, incluyendo el
procesamiento de macros, la interpretación y la compilación. Por último, la sección 1.5 trata de los
pasos de desarrollo del programa, incluyendo la especificación la prueba y la comprobación de la
corrección.
1.1 Introducción
° tienen objetivos de diseño comunes: encontrar lenguajes que sean sencillos de usar para los
humanos y eficientes de ejecutar para el hardware;
Algunos lenguajes de programación, sin embargo, son más similares entre sí, mientras que otros
son más diferentes entre sí. Basándose en sus similitudes o en los paradigmas, los lenguajes de
programación pueden dividirse en diferentes clases. En la definición de lenguaje de programación,
el paradigma es un conjunto de principios, conceptos y métodos básicos sobre cómo se expresa un
cálculo o un algoritmo. Los principales Los principales paradigmas que estudiaremos en este texto
son el imperativo, el orientado a objetos, el funcional y el lógico.
Cabe destacar que muchos lenguajes pertenecen a múltiples paradigmas. Por ejemplo, podemos
decir que C++ es un lenguaje de programación orientado a objetos. Sin embargo, C++ incluye casi
todas las características de C y, por tanto, es también un lenguaje de programación imperativo.
Podemos utilizar C++ para escribir programas en C. Java está más orientado a objetos, pero sigue
incluyendo muchas características imperativas. Por ejemplo, las variables de tipo primitivo de Java
no obtienen memoria del montón del lenguaje como otros objetos. Lisp contiene muchas
características no funcionales. Scheme puede considerarse un subconjunto de Lisp con menos
características no funcionales. Las operaciones aritméticas de Prolog se basan en el paradigma
imperativo.
Los lenguajes máquina consisten en instrucciones de números binarios puros que son difíciles de
recordar para los humanos. recordar. El siguiente paso en el desarrollo del lenguaje de
programación es el uso de mnemotecnia que permite ciertos símbolos para representar patrones
de bits de uso frecuente. El lenguaje de máquina con El lenguaje de máquina con un uso
sofisticado de mnemónicos se llama lenguaje ensamblador. Un lenguaje ensamblador
normalmente permite variables simples, bifurcarse a una dirección de etiqueta, diferentes modos
de direccionamiento y macros que representan un número de instrucciones. Se utiliza un
ensamblador para traducir un programa en lenguaje ensamblador al programa en lenguaje
máquina. máquina. El trabajo típico que realiza un ensamblador es traducir los símbolos
mnemónicos en números binarios correspondientes, sustituir las variables por números de
registro o posiciones de memoria, y calcular la dirección de destino de las instrucciones de
bifurcación según la posición de las etiquetas en el programa.
La invención del compilador se atribuye a Grace Hopper, que diseñó el primer compilador
ampliamente conocido conocido, llamado A0, en 1951.
El primer compilador primitivo, llamado Autocoder, fue escrito por Alick E. Glennie en 1952.
Traducía programas Autocode en declaraciones simbólicas a lenguaje de máquina para el
ordenador Manchester Mark I. Autocode podía manejar identificadores de una sola letra y
fórmulas sencillas.
El primer lenguaje ampliamente utilizado, Fortran (FORmula TRANslating), fue desarrollado por el
equipo dirigido por John Backus en IBM entre 1954 y 1957. Backus fue también el codiseñador del
sistema IBM 704 que ejecutó el primer compilador de Fortran. Posteriormente, Backus participó
en el desarrollo del lenguaje Algol y de la forma Backus-Naur (BNF). BNF era una notación formal
utilizada para definir la sintaxis de los lenguajes de programación. Fortran II llegó en 1958. Fortran
III llegó a finales de 1958, pero nunca se hizo público. Otras versiones de Fortran son ASA Fortran
66 (Fortran IV) en 1966, ANSI Fortran 77 (Fortran V) en 1978, ISO Fortran 90 en 1991 e ISO Fortran
95 en 1997. A diferencia de los lenguajes ensambladores, las primeras versiones de Fortran
permitían diferentes tipos de variables (reales, enteras, matrices), admitían la llamada a
procedimientos e incluían estructuras de control sencillas.
Basado en la experiencia de Fortran I, Algol 58 se anunció en 1958. Dos años más tarde, se
presentó Algol 60, el primer lenguaje estructurado en bloques. El lenguaje fue revisado en 1963 y
1968. Edsger
Dijkstra es el responsable del diseño del primer compilador de Algol 60. Es famoso por ser el líder
en la introducción de la programación estructurada y en la abolición de la sentencia goto de la
programación.
Basado en Algol, Pascal fue desarrollado por Niklaus Wirth entre 1968 y 1970. Además, desarrolló
Modula como sucesor de Pascal en 1977, luego Modula-2 en 1980 y Oberon en 1988. El lenguaje
Oberon tenía una sintaxis similar a la de Pascal, pero estaba fuertemente tipado. También ofrecía
una extensión de tipos (herencia) que que soportaba la programación orientada a objetos. En
Oberon-2, se introdujeron los procedimientos ligados al tipo (como los métodos en los lenguajes
de orientados a objetos).
El lenguaje de programación C fue inventado e implementado por primera vez por Dennis Ritchie
en DEC entre 1969 y 1973, como lenguaje de implementación de sistemas para el naciente sistema
operativo Unix. Pronto se convirtió uno de los lenguajes dominantes en la época e incluso en la
actualidad. Los predecesores de C fueron el lenguaje sin tipos BCPL (Basic Combined Programming
Language) de Martin Richards en 1967 y luego el B escrito por Ken Thompson en 1969. C tenía una
estructura de comprobación de tipos débil para permitir un mayor nivel de flexibilidad en la
programación.
Uno de los sucesores orientados a objetos de Simula fue Smalltalk, diseñado en Xerox PARC,
dirigido por Alan Kay. Las versiones desarrolladas fueron Smalltalk-72, Smalltalk-74, Smalltalk-76 y
Smalltalk-80. Smalltalk también heredó características de programación funcional de Lisp.
Basado en Simula 67 y C, Bjarne Stroustrup desarrolló en 1980 en los Laboratorios Bell un lenguaje
llamado "C con clases", que fue revisado y renombrado como C++ en 1983. C++ se consideraba un
C mejor (por ejemplo, con una fuerte comprobación de tipos), además de soportar la abstracción
de datos y la programación orientada a objetos heredada de Simula 67.
Java fue escrito por James Gosling, Patrick Naughton, Chris Warth, Ed Frank y Mike Sheridan en
Sun Microsystems. Al principio se llamaba Oak y luego pasó a llamarse Java cuando se anunció
públicamente en 1995. Los predecesores de Java fueron C++ y Smalltalk. Java eliminó la mayoría
de las características no orientadas a objetos de C++ y era un lenguaje de programación más
sencillo y mejor orientado a objetos. Su concepto de procesamiento de programas en dos niveles
de procesamiento de programas en dos niveles (es decir, compilación en un bytecode intermedio
y luego interpretación del bytecode mediante una pequeña máquina virtual) lo convirtió en el
lenguaje dominante para la programación de aplicaciones de Internet. Java todavía no era un
lenguaje de programación orientado a objetos puro. Sus tipos primitivos, enteros, de punto
flotante de punto flotante, booleanos, etc., no eran clases, y sus asignaciones de memoria se
hacían desde la pila del lenguaje en lugar de la pila del lenguaje.
El lenguaje C# de Microsoft se anunció por primera vez en junio de 2000. El lenguaje se derivó de
C++ y Java. Se implementó como un lenguaje completamente orientado a objetos sin tipos
"primitivos". C# también C# también hace hincapié en la programación orientada a componentes,
que es una versión refinada de la programación orientada a objetos. orientada a objetos. La idea
es poder ensamblar sistemas de software a partir de componentes prefabricados.
Como dialecto de Lisp, Scheme fue desarrollado por primera vez por G. L. Steele y G. J. Sussman en
1975 en el MIT. Varias importantes mejoras en sus versiones posteriores, incluyendo una mejor
regla de alcance, procedimientos (funciones) como objetos de primera clase, la eliminación de los
bucles y la dependencia exclusiva de las llamadas a procedimientos recursivos para para expresar
los bucles. Scheme fue estandarizado por el IEEE en 1989.
En 1981 comenzaron los esfuerzos para desarrollar un dialecto común de Lisp, denominado
Common Lisp. Common Lisp pretendía ser compatible con todas las versiones existentes de los
dialectos de Lisp y crear un gran producto comercial. Sin embargo, el intento de fusionar Scheme
con Lisp fracasó, y Scheme sigue siendo hoy un dialecto de Lisp independiente. dialecto
independiente de Lisp. Common Lisp fue estandarizado por el IEEE en 1992.
Además de Lisp, el lenguaje FP de John Backus también forma parte de los primeros lenguajes de
programación funcional. FP no se basaba en el cálculo lambda, sino en unas cuantas reglas para
combinar formas de funciones. Backus consideraba que la expresividad del cálculo lambda sobre
las funciones computables era mucho más amplia de lo necesario. A conjunto de reglas
simplificadas podría hacer un mejor trabajo.
Existen muchos lenguajes de programación basados en la lógica. Por ejemplo, ALF (Algebraic Logic
Functional language) es un lenguaje funcional y lógico integrado basado en cláusulas de Horn para
la programación lógica, y en funciones y ecuaciones para la programación funcional. Gödel es un
lenguaje de programación lógica fuertemente tipado. El sistema de tipos se basa en una lógica
multiordenada con polimorfismo paramétrico. RELFUN amplía la lógica de Horn mediante el uso
de una sintaxis de orden superior, dominios finitos de primera clase y expresiones de funciones no
deterministas y sin base, que se distinguen explícitamente de las estructuras.
Esta sección estudia las estructuras de los lenguajes de programación en función de cuatro capas
estructurales: léxica, sintáctica, contextual y semántica.
° Identificadores: Nombres que pueden ser elegidos por los programadores para representar
objetos como variables, etiquetas, procedimientos y funciones. La mayoría de los lenguajes de
programación requieren que un identificador comience con una letra alfabética y puede ser
seguido opcionalmente por letras, dígitos y algunos caracteres especiales.
° Palabras clave: Nombres reservados por el diseñador del lenguaje y utilizados para formar la
estructura sintáctica del mismo.
° Operadores: Símbolos utilizados para representar las operaciones. Todos los lenguajes de
programación de propósito general deben proporcionar ciertos operadores mínimos, como
operadores matemáticos como +, , *, /, operadores relacionales como <, , ==, >, , y operadores
lógicos como AND, OR, NOT, etc.
° Separadores: Símbolos utilizados para separar unidades léxicas o sintácticas del lenguaje. Se
utilizan como separadores el espacio, la coma, los dos puntos, el punto y coma y los paréntesis.
° Literales: Valores que se pueden asignar a variables de diferentes tipos. Por ejemplo, los literales
de tipo entero son números enteros, los literales de tipo carácter son cualquier carácter del
conjunto de caracteres del lenguaje, y los literales de tipo cadena son cualquier cadena de
caracteres.
° Asignaciones: Una sentencia de asignación asigna un valor literal o una expresión a una variable.
° Sentencias condicionales: Una sentencia condicional comprueba una condición y pasa a una
determinada sentencia en función del resultado de la prueba (verdadero o falso). Las sentencias
condicionales típicas son if-then, ifthen- else y switch (case).
° Sentencias de bucle: Una sentencia de bucle comprueba una condición y entra en el cuerpo del
bucle o sale de él en función del resultado de la prueba (verdadero o falso). Las sentencias de
bucle típicas son for-loop y while-loop.
La estructura contextual (también llamada semántica estática) define la semántica del programa
antes de la ejecución dinámica. Incluye la declaración de variables, la inicialización y la
comprobación de tipos.
Algunos lenguajes imperativos requieren que todas las variables sean inicializadas cuando son
declaradas en la capa contextual, mientras que otros lenguajes no requieren que las variables sean
inicializadas cuando son declaradas, siempre y cuando las variables sean inicializadas antes de que
sus valores sean utilizados. Esto significa que la inicialización puede realizarse tanto en la capa
contextual como en la capa semántica.
La estructura contextual empieza a ocuparse del significado del programa. Una declaración que es
léxicamente correcta puede no ser contextualmente correcta. Por ejemplo:
Todas las declaraciones son léxicamente correctas, pero la última declaración es contextualmente
incorrecta porque no tiene sentido añadir una variable entera a una variable de cadena.
En la Sección 1.3 se tratará más sobre los tipos de datos, la comprobación de tipos y la
equivalencia de tipos.
en los fundamentos matemáticos y lógicos en los que se basan los lenguajes. Por ejemplo, los
significados de los procedimientos de Scheme son los mismos que los significados de las
expresiones lambda en el cálculo lambda, en el que se basa Scheme. en el que se basa Scheme, y
los significados de las cláusulas de Prolog son los mismos que los de las cláusulas de la lógica de
lógica de Horn en la que se basa Prolog.
BNF (Backus-Naur Form) es un metalenguaje que puede utilizarse para definir las estructuras
léxicas y sintácticas de otro lenguaje. En lugar de aprender primero el lenguaje BNF y luego usar
BNF para definir un nuevo lenguaje, primero usaremos BNF para definir un lenguaje inglés
simplificado con el que estemos familiarizados, y luego aprenderemos BNF a partir de la propia
definición.
Una frase simple en inglés está formada por un sujeto, un verbo y un objeto. El sujeto, a su vez,
está formado por uno o varios adjetivos seguidos de un sustantivo. El objeto tiene la misma
estructura gramatical. Los verbos y adjetivos deben proceder del vocabulario. Formalmente,
podemos definir una frase inglesa simple como sigue:
En las definiciones, el símbolo "::=" significa que el nombre del lado izquierdo está definido por la
expresión del lado derecho. El nombre entre un par de paréntesis angulares "<>" es no terminal, lo
que significa que el nombre debe definirse con más detalle. La barra vertical "|" representa una
relación "o". Los nombres en negrita son terminales, lo que significa que los nombres no necesitan
definirse más. Forman el vocabulario del lenguaje.
Podemos utilizar la definición de la frase para comprobar si las siguientes frases son
sintácticamente correctas.
La primera frase es sintácticamente correcta, aunque no tiene mucho sentido. Los tres adjetivos
de la frase son correctos porque la definición de adjetivo permite utilizar cualquier número de
adjetivos en el sujeto y en el objeto de la frase. La segunda y tercera frases también son
sintácticamente correctas según la definición. Las frases cuarta y quinta son sintácticamente
incorrectas porque falta un sustantivo en el objeto de las frases. La sexta frase es incorrecta
porque "no" no es un terminal. La última frase es incorrecta porque la definición no permite que la
frase comience con un verbo.
Después de tener una comprensión básica de BNF, podemos utilizarlo para definir un pequeño
lenguaje de programación. Las primeras cinco líneas definen la estructura léxica, y el resto define
la estructura sintáctica del lenguaje.
Ahora utilizamos la definición para comprobar cuáles de las siguientes afirmaciones son
sintácticamente correctas.
Según la definición BNF de la lengua, las afirmaciones 1 y 2 son correctas. Las afirmaciones 3 y 4
son incorrectas porque 3b y 2sum no son identificadores ni expresiones aceptables. La afirmación
5 es incorrecta. La afirmación 6 es incorrecta porque un identificador debe empezar por una letra.
La afirmación 7 es incorrecta porque el lado izquierdo de una sentencia de asignación debe ser un
identificador.