Escuela Técnica Superior de Ingenieros Informáticos

Universidad Politécnica de Madrid

Procesadores de Lenguajes

Estás aquí:

Inicio > Práctica > Lenguaje

Introducción a JS-PdL para la Práctica de "Procesadores de Lenguajes"

Curso 2023/2024


Contenido:


Generalidades

JS es un lenguaje de programación ideado en 1995 en Netscape a partir de los lenguajes C, C++ y Java.

Este resumen presenta las principales características de la variante de JS denominada JS-PdL que es la que hay que utilizar para la práctica de la asignatura. No hay que considerar los elementos de JS no mencionados en este resumen y se deben considerar los elementos y características tal como aparecen aquí descritos. Con el fin de facilitar la implementación de la Práctica, las características mostradas en esta página pueden no coincidir al 100% con el estándar del lenguaje JS, por lo que, en caso de duda, se deberá implementar siempre el comportamiento aquí descrito. Entre corchetes se dan indicaciones sobre la obligatoriedad u opcionalidad de algunas partes del lenguaje en cuanto a su implementación.

JS-PdL es un lenguaje en el que se diferencian las minúsculas y las mayúsculas (es case sensitive).

JS-PdL es un lenguaje de formato libre, es decir, que se admiten espacios, tabuladores, saltos de línea y comentarios en cualquier parte del código. Las sentencias simples y las declaraciones de variables finalizan en punto y coma.

Las palabras clave que tiene el lenguaje son reservadas (se escriben siempre en minúsculas). Cada grupo de prácticas sólo ha de tener en cuenta las palabras asignadas a su grupo.

JS-PdL es un lenguaje con estructura de bloques que se definen mediante la utilización de las llaves { } y, por tanto, maneja los conceptos de identificadores globales y locales. Los identificadores declarados fuera de cualquier función son globales y pueden ser utilizados desde cualquier función definida con posterioridad. Los declarados en el interior de una función son locales a dicha función.

En JS-PdL no es obligatorio declarar todos los identificadores antes de que se utilicen; en este caso, un uso de un identificador no declarado se considera como una variable global entera. Además, hay que realizar la implementación considerando que es un lenguaje con recursividad, por lo que cualquier función puede ser recursiva. El lenguaje no permite la definición de funciones anidadas.

Estructura de un Programa

Debe considerarse que un programa en JS-PdL estará compuesto por un único fichero que puede tener declaraciones de variables globales, sentencias y declaración de funciones, en cualquier orden.

En este enlace se muestra un ejemplo de un fichero válido según el lenguaje descrito en esta asignatura.

Programa Principal

El programa principal (por donde comenzará la ejecución del programa) estará formado por todas las sentencias ubicadas fuera de las funciones.

Por tanto, la ejecución comenzaría por la primera sentencia que se encuentre en el fuente (fuera de una función) y proseguiría secuencialmente hasta el final del fichero ejecutando todas las sentencias situadas fuera de las funciones. Hay que tener en cuenta que una función se ejecuta únicamente cuando es invocada.

Comentarios

En JS-PdL hay dos tipos de comentarios [cada grupo deberá implementar obligatoriamente solo el que le corresponda]:

  1. Comentario de bloque: Se utilizan los caracteres /* para abrir el comentario, y */ para cerrarlo. No se permiten comentarios anidados. Los comentarios pueden ocupar más de una línea y pueden ir colocados en cualquier parte del código:
    /* ¡Comentario con apertura y cierre! */
  2. Comentario de línea: Los comentarios comienzan por los caracteres // y finalizan al acabar la línea. Este tipo de comentario sólo ocupa una línea y puede ir colocado en cualquier parte del código:
    // Comentario de línea...

Constantes

El lenguaje dispone de varios tipos de constantes [implementación obligatoria de las constantes enteras y cadenas]:

Enteras

Para representar las constantes enteras se utilizan los dígitos decimales. Por ejemplo: 378.

Los números enteros se tienen que poder representar con una palabra (16 bits, incluido el signo), por lo que el máximo entero válido será el 32767.

Cadenas de Caracteres

Las constantes cadena van encerradas entre comillas dobles ("¡Hola, mundo!") o entre comillas simples ('¡Hola, mundo!') [cada grupo deberá implementar obligatoriamente solo la que le corresponda]. Se utiliza internamente el carácter nulo (cuyo código ASCII es 0) como carácter de fin de cadena. Puede aparecer cualquier carácter imprimible en la cadena (por tanto, no es válido un salto de línea como tal; para usar el salto de línea, se pueden emplear las secuencias de escape).

Para representar caracteres especiales dentro de una cadena se utiliza una secuencia de escape. Una secuencia de escape se representa mediante el carácter barra inversa seguido de un determinado carácter. Algunos de estos caracteres son: el salto de línea (\n) o el carácter de barra inversa (\\) [la implementación de estos caracteres especiales es opcional].

Una cadena no puede contener más de 64 caracteres.

Lógicas

En JS-PdL existen dos constantes lógicas para representar verdadero y falso: true y false [es opcional implementar las constantes lógicas, que son las palabras reservadas true y false].

Operadores

Este lenguaje presenta un conjunto de operadores con los que escribir distintas expresiones. Además, se pueden utilizar los paréntesis para agrupar subexpresiones [es obligatorio implementar los paréntesis]. Las expresiones pueden tener varios operadores, varios operandos, paréntesis... Las expresiones se pueden utilizar en multitud de construcciones del lenguaje: asignaciones, condiciones, parámetros de una función, instrucciones de salida, instrucciones de retorno...

Operadores Aritméticos

Son los operadores que permiten realizar la suma, resta, producto, división y módulo: +, -, *, / y % [obligatorio implementar al menos uno y dos como máximo]. Se aplican sobre datos enteros, proporcionando un resultado entero (en el caso de la división, redondeando el valor si es necesario).

También existen los operadores más y menos unarios: +, - [implementación opcional]. Estos operadores se pueden utilizar delante de una constante entera, una variable o una expresión.

Operadores de Relación

Son los operadores que permiten realizar las comparaciones de igual, distinto, menor, mayor, menor o igual, mayor o igual: ==, !=, <, >, <= y >= [obligatorio implementar al menos uno de los operadores y dos como máximo]. Se aplican sobre datos enteros y proporcionan un resultado lógico.

Operadores Lógicos

Representan las operaciones de conjunción, disyunción y negación: &&, || y ! [obligatorio implementar al menos uno y dos como máximo]. Se aplican sobre datos lógicos y devuelven un resultado lógico.

Operadores de Incremento y Decremento

Permiten auto-incrementar o auto-decrementar el valor de una variable entera: ++ y -- (pueden actuar como prefijos o como sufijos) [algunos grupos tienen que implementar uno de estos operadores]. Se aplican sobre variables enteras y devuelven un resultado entero modificando también el valor de la variable. Ejemplo:

a = j++; /* si j valía 5, ahora a == 5 y j == 6 */
a = ++j; /* si j valía 5, ahora a == 6 y j == 6 */

Operadores de asignación

Permiten realizar asignaciones simples o realizando simultáneamente una operación: = (asignación), += (asignación con suma), -= (asignación con resta), *= (asignación con producto), /= (asignación con división), %= (asignación con módulo), &= (asignación con y lógico) y |= (asignación con o lógico) [todos los grupos tienen que implementar la asignación simple (=) y algunos grupos deberán implementar uno de los operadores de asignación con operación]. Ejemplo:

n += m;    /* es equivalente a n = n + m */
b1 &= b2;  /* es equivalente a b1 = b1 && b2 */

No se permite usar estos operadores de asignación como parte de las expresiones.

Precedencia de Operadores

En la tabla siguiente se muestra la precedencia de los operadores con el siguiente significado: los operadores del mismo grupo tienen la misma precedencia y, conforme se desciende por la tabla, la precedencia aumenta. La asociatividad de cada grupo de operadores se indica también en la tabla. En cualquier caso, el uso de paréntesis permite alterar el orden de evaluación de las expresiones [es obligatorio para todos los grupos tener en cuenta la precedencia y asociatividad de los operadores utilizados].

Precedencias de los Operadores
Más información

Tabla con la relación de todos los operadores de JS-PdL con su significado, orden de prioridad y relación de asociatividad. La primera columna muestra los operadores, la segunda su significado y la tercera la asociatividad.

Operadores Significado Asociatividad
|| O lógico Izquierda a derecha
&& Y lógico Izquierda a derecha
==
!=
Igual
Distinto
Izquierda a derecha
>
>=
<
<=
Mayor
Mayor o igual
Menor
Menor o igual
Izquierda a derecha
+
-
Suma
Resta
Izquierda a derecha
*
/
%
Producto
División
Módulo
Izquierda a derecha
!
++
--
+
-
Negación lógica
Autoincremento
Autodecremento
Más unario
Menos unario
Derecha a izquierda

Identificadores

Los nombres de identificadores están formados por cualquier cantidad de letras, dígitos y subrayados (_), siendo el primero siempre una letra o un subrayado. Ejemplos: a, a3, A3, Sueldo_de_Trabajador, _z__9_9__...

Como ya se ha dicho, el lenguaje diferencia minúsculas y mayúsculas, por lo que los nombres a3 y A3 son identificadores distintos.

Declaraciones

El lenguaje JS-PdL no exige declaración explícita de las variables que se utilicen. En el caso de que se use un nombre de variable que no ha sido declarado previamente, se considera que dicha variable es global y entera (declaración implícita).

Para realizar una declaración explícita de una variable, se coloca la palabra let seguida del nombre de la variable y del tipo (que deberá ser entero, lógico o cadena).

let var0 Tipo;

Pueden realizarse declaraciones explícitas en cualquier lugar dentro de una función; en este caso, la variable será local y visible desde ese punto hasta el final de la función. También pueden realizarse declaraciones explícitas fuera de las funciones en cualquier parte del código (variables globales), pero esas variables solo pueden utilizarse a partir de dicha línea.

Opcionalmente, puede inicializarse una variable en la misma instrucción de la declaración, colocando el operador de asignación (=) seguido de una expresión [es opcional implementar la inicialización de variables].

let var4 Tipo = expresión4;

Si una variable no se inicializa cuando se declara, se realiza una inicialización por omisión basándose en su tipo: 0 si es entera, falso si es lógica y la cadena vacía ("" o '') si es cadena.

En resumen, el ámbito de una variable será global si se declara fuera de cualquier función, y será local si se declara dentro del cuerpo de una función. Cualquier otro bloque (por ejemplo, los usados por las sentencias de control) no define un ámbito nuevo. Por otro lado, el nombre de las funciones siempre estará en el ámbito global. No se admite la redeclaración del mismo identificador en un mismo ámbito.

Tipos de Datos

El lenguaje dispone de distintos tipos de datos básicos. Se deben considerar sólo los siguientes tipos de datos básicos: entero, lógico, cadena y vacío.

El tipo entero se refiere a un número entero que debe ocupa un tamaño de 1 palabra (16 bits). Se representa con la palabra int.

El tipo lógico se refiere a un valor lógico. Se representa con la palabra boolean. El tipo lógico se almacena como un entero, por lo que ocupa también un tamaño de 1 palabra (16 bits). Las expresiones relacionales y lógicas devuelven un valor lógico.

El tipo cadena se refiere a una secuencia de caracteres. Se representa mediante string y una variable de tipo cadena ocupa 64 palabras (128 bytes), es decir, un máximo de 64 caracteres.

El tipo vacío permite indicar la ausencia de tipo. Se representa mediante la palabra void y solamente tiene sentido como el tipo de retorno de una función o para indicar ausencia de parámetros en una función. No se pueden declarar variables de tipo vacío.

El lenguaje no tiene conversiones automáticas entre tipos.

Ejemplos:

let i int = 11;        // variable entera
let st string;         // variable cadena 
let b boolean;         // variable lógica
let c int = 66+i;      // variable entera
b = i != c + 1;        // i y c+1 son enteros; b valdrá verdadero
c = c + i;             // i y c son enteras; c valdrá 88
i = b + i;             // Error: no se puede sumar un lógico con un entero
b = ! i;               // Error: el operador de negación solo puede aplicarse a lógicos

Instrucciones de Entrada/Salida

Las instrucciones de entrada/salida disponibles en el lenguaje son dos. Su uso tiene la sintaxis de una sentencia.

La instrucción put expresión evalúa la expresión e imprime el resultado por pantalla. La expresión puede ser de tipo cadena o entera. Por ejemplo:


c= 50; put c * 2 + 16 ; /* imprime: 116 */
a= 'Adiós';
put 'Hola'; put a;    // imprime HolaAdiós

La instrucción get variable lee un número o una cadena del teclado y lo almacena en la variable variable, que tiene que ser, respectivamente, de tipo entero o cadena. Por ejemplo:

let a int;
let c string;
get a;     /* lee un número */
put a * a; // imprime el cuadrado del número leído 
put"Pon tu nombre";
get  c;    /* lee una cadena */
put ("Hola, ");
put(c);    // imprime las cadenas

Sentencias

De todo el grupo de sentencias del lenguaje JS, se han seleccionado para ser implementadas las que aparecen a continuación [opcional u obligatoriamente, según se indique en cada caso]. Además de las sentencias aquí indicadas, también se consideran sentencias en este lenguaje las instrucciones de entrada/salida (put y get), así como las declaraciones de variables.

Sentencias de Asignación

Existe una sentencia de asignación en JS-PdL, que se construye mediante el símbolo de asignación = [es obligatorio implementar la sentencia de asignación por todos los grupos; los grupos que tengan el operador de asignación con operación deberán implementar también la sentencia de asignación con operación con el operador asignado]. Su sintaxis general es la siguiente: variable, operador-asignación y expresión. Esta sentencia asigna a la variable el resultado de evaluar la expresión:

i= 8 + 6;

Como ya se ha indicado, no hay conversiones entre tipos, por lo que tanto el identificador como la expresión han de ser del mismo tipo.


let i int = 123; // i es una variable entera
let cad string;
put i;         // imprime el valor entero 123
cad= 'hola';
put cad;       // imprime el valor cadena "hola"
i = i > 88;   // Error: no se puede asignar un lógico a un entero

Sentencia de Llamada a una Función

Esta sentencia permite invocar la ejecución de una función que debe estar previamente definida [implementación obligatoria].

La llamada a una función se realiza mediante el nombre de la función seguido de los parámetros actuales (separados por comas) entre paréntesis (si no tiene parámetros, hay que poner los paréntesis vacíos). Los parámetros pueden ser cualquier expresión válida en el lenguaje:

p1 (5);         /* llamada a una función con un argumento entero */ 
p2 ();          /* llamada sin parámetros a una función */ 
p3 ("", i - 8); /* llamada con dos argumentos a una función */

Los parámetros actuales en la llamada tienen que coincidir en número y tipo con los parámetros formales de la declaración de la función.

Si una función devuelve un valor, podrá incluirse una llamada a dicha función dentro de cualquier expresión. Si la llamada se realiza como una sentencia (no se realiza en una expresión), se invocará a la función pero el valor devuelto se perderá:


if (fun1 (9))    /* llamada a una función con un argumento entero */ 
c= b + fun2 (b, fun3() != 8); /* llamada con dos argumentos a una función, 
                 siendo fun3, una llamada a otra función sin argumentos */
fun2 (c, true);  /* el valor devuelto por fun2 se pierde */

Sentencia de Retorno de una Función

JS-PdL dispone de la sentencia return para finalizar la ejecución de una función y volver al punto desde el que fue llamada [implementación obligatoria].

Una función finalizará su ejecución cuando se ejecute una instrucción return o al llegar al final del cuerpo de la función (es decir, no es obligatorio que aparezca la instrucción return).

Si una función tiene tipo devuelto, sus sentencias return deberán contener una expresión. El tipo de la expresión retornada deberá coincidir con el tipo devuelto de la función.

Si una función no tiene tipo devuelto (void), sus sentencias return no deberán contener una expresión.

No es necesario que todas las funciones tengan instrucción de retorno (independientemente del tipo devuelto con que se haya declarado la función) ni tampoco hay ninguna restricción a la cantidad o ubicación de las instrucciones de retorno dentro de una función.

function SumaAlCuadrado int (int a, int b)
{
  j= a + b;
  return j * j;
  /* La función finaliza y devuelve el valor entero de la expresión */
}
function pro void (int x)
{
  x= SumaAlCuadrado (x - 1, x);
   /* x contendrá el valor devuelto por la función: (x+x-1)^2 */
  if (x > (194/2)) return; /* finaliza la ejecución si se ejecuta */
  put SumaAlCuadrado (x, x);
} /* finaliza la ejecución si antes no se ejecutó el return */

Sentencia Condicional simple

Selecciona la ejecución de una sentencia, dependiendo del valor correspondiente de una condición de tipo lógico [implementación obligatoria para todos los grupos]:

if (condición) sentencia

Si la condición lógica se evalúa como cierta, se ejecuta la sentencia que puede ser cualquier sentencia simple del lenguaje, es decir, asignación, instrucción de entrada/salida, llamada a función o retorno (también break o sentencias de auto-incremento o auto-decremento [para los grupos que tengan dichas opciones]); en caso contrario, se finaliza su ejecución:

if (a > b) c= b;
if (fin) put("adiós");

Sentencia Condicional compuesta

Selecciona la ejecución de una de las secuencias de sentencias que encierra, dependiendo del valor correspondiente de una condición de tipo lógico. Tiene dos formatos [implementación obligatoria de ambos para los grupos que les corresponda]:

  • if (condición)
    {
       cuerpo1
    }
  • if (condición) 
    {
       cuerpo1
    }
    else 
    {
       cuerpo2
    }

Si la condición lógica se evalúa como cierta, se ejecuta el cuerpo1; en caso contrario, se ejecuta el cuerpo2 (si el programador lo ha escrito). Cada uno de estos cuerpos contendrán cero, una o más sentencias o declaraciones, siempre entre llaves.

if (a > b)
{
  c= b;
}
else 
{
  c= a;
  if (fin)
  {
    put"adiós";
  }
}

Sentencia Repetitiva while

Esta sentencia permite repetir la ejecución de unas sentencias basándose en el resultado de una expresión lógica [implementación obligatoria para algunos grupos]. La sintaxis es:

while (condición) 
{
   cuerpo
}

Se evalúa la condición lógica y, si resulta ser cierta, se ejecuta el cuerpo (que será un bloque de sentencias o declaraciones de variables entre llaves). Este proceso se repite hasta que la condición sea falsa:

while (n <= 10) 
{
    n= n + 1;
    put n;
} // mientras que n sea menor o igual que 10...

Sentencia Repetitiva do while

Esta sentencia permite repetir la ejecución de las sentencias del bucle mientras se cumpla una condición [implementación obligatoria para algunos grupos]. La sintaxis es:

do {
   cuerpo
} while (condición);

En esta instrucción se ha de colocar un bloque de sentencias o declaraciones de variables encerradas entre llaves. Primero, se ejecuta el cuerpo; seguidamente, se evalúa la condición lógica y, si resulta ser cierta, se ejecuta de nuevo el cuerpo. Este proceso se repite hasta que la condición sea falsa:

do {
  c= a++;
  c*= b;
} while (a < b);

Sentencia Repetitiva for

Esta sentencia for permite ejecutar un bucle según una condición [implementación obligatoria para algunos grupos]. La sintaxis es:

for (inicialización; condición; actualización)
{
   cuerpo
}

La inicialización debe ser una sentencia de asignación o nada; la condición debe ser una expresión lógica; y la actualización puede ser una asignación (sencilla o con operación [para los grupos que tengan esta opción]), un autoincremento o autodecremento [para los grupos que tengan esta opción] o estar vacía. El cuerpo (con cero, una o más sentencias o declaraciones de variables) está en un bloque delimitado por llaves.

El funcionamiento de este bucle es como sigue:

  1. Se ejecuta la inicialización
  2. Se evalúa la condición
  3. Si la condición lógica es falsa, se abandona la ejecución del bucle
  4. Se ejecuta el cuerpo
  5. Se ejecuta la actualización
  6. Se vuelve al paso 2.
for (i = 1; i < 10; i++)
{
 f *= i;
}

Sentencia de Selección Múltiple

Esta sentencia selecciona y ejecuta unas sentencias basándose en el resultado de una expresión [implementación obligatoria para algunos grupos]. La sintaxis de la sentencia de selección múltiple es:

switch (expresión)
{
  case valor1: cuerpo1
  case valor2: cuerpo2
  /* . . . */
  default: cuerpon
}

Su funcionamiento es como sigue: Se evalúa la expresión (que debe ser de tipo entero), se busca el valor que coincida con el resultado (los valores tienen que ser constantes enteras) y se ejecuta su cuerpo asociado (cada cuerpo puede estar formado por cero, una o más sentencias o declaraciones de variables). Una vez ejecutado, se continúa la ejecución de todos los cuerpos asociados a todos los valores que se encuentren a continuación hasta el final del switch. Si no se encuentra el valor, se ejecutan las sentencias asociadas a default, si el programador la ha incluido [el default es opcional para la implementación]:

switch (dia)
{
   case 1: put 'lunes';
   case 2: put 'martes';
   case 3: put 'miércoles';
   case 4: put 'jueves';
   case 5: 
           put 'viernes';
   default: put'fiesta';
} /* si dia == 4, se imprimirá: jueves viernes fiesta */

Sentencia break

Esta sentencia aborta la ejecución de un switch [implementación obligatoria para los grupos que tengan switch]. No hay ninguna restricción en cuanto al lugar o número de veces que se puede poner la sentencia break en cada case:

switch (dia)
{
   case 0: break;
   case 1: put "lunes"; break;
   case 2: put "martes";
   case 3: put "miércoles";
           break;
   case 4: put "jueves"; break;
   case 5: put "viernes"; break;
   case 6: if (error) break; put("sábado");
   default: if (dia < 8) put  "fiesta";
} /* si dia == 4, se imprimirá: jueves */

Funciones

Es necesario definir cada función antes de poder utilizarla. La definición de una función se realiza indicando la palabra function, el nombre, el tipo de retorno y, entre paréntesis, los parámetros (si existen) con sus tipos. Tras esta cabecera va un bloque (delimitado por llaves) con el cuerpo de la función (que puede tener cualquier cantidad de sentencias o declaraciones de variables):

function nombre Tipo (lista de argumentos)
{
   sentencias | declaración de variables
}

Las funciones pueden devolver un valor de uno de los tipos básicos del lenguaje (entero, lógico o cadena) o no retornar nada (en este caso, se debe indicar que la función retorna void). El tipo de retorno de la función se determina según el Tipo que aparezca en su declaración. En caso de que las instrucciones return de una función tengan expresiones de un tipo distinto al declarado, será un error. No es obligatorio que una función tenga una instrucción return en su cuerpo ni que tenga que ser la última instrucción.

La lista de argumentos (que puede estar vacía y, en este caso, se ponen los paréntesis con la palabra void en su interior) consta del tipo y del nombre de cada parámetro formal. Si hay más de un argumento, se separan por comas. Los parámetros se pasan siempre por valor.

Las funciones pueden recibir como parámetros cualquiera de los tipos básicos del lenguaje (entero, lógico o cadena).

JS-PdL admite recursividad. Todos los grupos de prácticas han de considerarla en su implementación. Cualquier función puede ser recursiva, es decir, puede llamarse a sí misma.

El lenguaje JS-PdL no permite la definición de funciones anidadas. Esto implica que dentro de una función no se puede declarar ni definir otra función.

Dentro de una función se tiene acceso a las variables globales, a sus argumentos y a sus variables locales. Si en una función se declara una variable local o un argumento con el mismo nombre que un identificador global, este último no es accesible desde dicha función.

function hola void (void) // función sin parámetros
{
   put"Hello!";
}
let x int;  // global
function factorial int (int x) 
   /* se define la función recursiva con un parámetro, 
      que oculta a la variable global de igual nombre */
{
  hola();
  if (x > 1) 
    return x * factorial (x - 1);
  return 1;
}	// la función devuelve un entero
function Suma boolean (int aux, int fin, boolean b)
  /* se define la función Suma que recibe 
     dos enteros y un lógico */
  /* usa la variable global x */ 
{
    for (x= 1; (x < fin) && b; x= x + 2)
    {
      aux += factorial (aux-1);
    }
    return aux > 10000;
}	// la función devuelve un lógico
function Imprime void (int a)
{
    put (a);
    return;	// esta instrucción se podría omitir
}	// la función no devuelve nada
get x;
Imprime (factorial (Suma (x, 3, true)));  
// se llama a las tres funciones

Más Información sobre el Lenguaje

Hay que tener en cuenta que para esta práctica no es necesario tener un conocimiento total del lenguaje JS. Tan solo hay que incorporar el funcionamiento del pequeño subconjunto del lenguaje JS-PdL que se ha explicado aquí, necesario para implementar las partes comunes a todos los grupos, así como las partes obligatorias de cada grupo. Por tanto, no se deben incluir todas las características, variantes y elementos que tiene el lenguaje JS y, en caso de inconsistencia, deberá elegirse el comportamiento aquí descrito.

Aquí se tiene un ejemplo de un fichero que incorpora la mayoría de las funcionalidades descritas en esta página, a modo de ejemplo adicional para facilitar su compresión.

En cualquier caso, se puede encontrar más información sobre JS en la página de referencias, en los libros que hay en la Biblioteca de la Escuela (se puede usar el buscador de la UPM), así como en cualquier libro, manual o documentación del lenguaje (buscando en librerías como Amazon). También se pueden encontrar otras fuentes de información realizando búsquedas en la Web o en los siguientes enlaces: