Skip to content

Especificación

Extracción de Requisitos

De entre todos los requisitos enumerados en la descripción del Lenguaje, se extraen a continuación los correspondientes al analizador sintáctico.

Aspectos generales:

  • La sección DATA deberá aparecer obligatoriamente antes de la sección CODE y cada una de ellas solo puede aparecer una vez.
  • Tanto las sentencias como las definiciones terminan con un punto y coma ;.

Sección de Datos:

  • En la sección DATA se realizan las definiciones de variables (no puede haber definiciones en la sección CODE).
  • No es obligatorio que se definan variables pero, en cualquier caso, tiene que aparecer la palabra reservada DATA.
  • Las variables solo pueden ser de tipo int (2 bytes) o float (4 bytes). Nótese que de este requisito sólo es relevante para esta fase el hecho de que hay dos tipos, pero no su tamaño.
  • En cada definición sólo puede haber una variable (por ejemplo, no se permite int a,b;)

Sección de Código:

  • En la sección CODE aparecerán las sentencias del programa (no puede haber sentencias en la sección DATA).
  • Un programa puede no tener ninguna sentencia pero, en cualquier caso, es obligatorio que aparezca la palabra reservada CODE.
  • En la sección CODE puede haber dos tipos de sentencias: escritura (print) y asignación.
  • Las expresiones podrán estar formadas por literales enteros, literales reales y variables, pudiendo combinarse todos ellos mediante operadores aritméticos (+, -, * y /). Los operadores tendrán la prioridad y asociatividad habitual.
  • Se podrán agrupar expresiones mediante paréntesis.

Estos requisitos se pueden observar en el programa de ejemplo:

c
DATA
	float price;
	int width;
	int height;
	float total;

CODE
	price = 9.95;
	total = (price - 3.0) * 1.18;
	print total;

	width = 10; height = 20;
	print 0 - width * height / 2;

Especificación con Gramática Libre de Contexto

A continuación hay que modelar los requisitos anteriores de manera formal con un metalenguaje. En este tutorial se usará como metalenguaje las gramáticas libres de contexto (GLC). Los requisitos extraídos anteriormente, expresados en una GLC mediante BNF, son:

java
program ⟶ 'DATA' varDefinitions* 'CODE' statements*

varDefinition ⟶ type IDENT ';'

type ⟶ 'float' | 'int'

statement ⟶ 'print' expression ';'
            | expression '=' expression ';'

expression ⟶
     expression '+' expression
	| expression '-' expression
	| expression '*' expression
	| expression '/' expression
	| '(' expression ')'
	| IDENT
	| INT_LITERAL
	| FLOAT_LITERAL

A la hora de construir una gramática es muy recomendable que, a la hora de crear cada regla, se plantee ésta como una y sólo una de las tres construcciones básicas:

  • Secuencias. Indican el orden el que deben aparecer los símbolos de la estructura.
  • Listas. Indican que la estructura se forma repitiendo otra estructura.
  • Composiciones. En una composición se definen las formas atómicas (básicas) de la estructura para luego formar estructuras mayores que se apoyan en las primeras.

La gramática anterior se ha construido siguiendo estas pautas:

  • Se ha definido programa como una secuencia que indica que lo primero son las variables y luego las sentencias. Otros ejemplos de la construcción secuencia son los no-terminales variable, tipo y sentencia, que indican respectivamente cómo se define una variable y cómo se ordenan una escritura y una asignación.
  • Los no-terminales variables y sentencias se han definido mediante listas (en este caso mediante el patrón de cero o más elementos sin separadores).
  • Por último, expression es una composición en la que se definen sus casos atómicos (identificadores y literales) y luego se define cómo se forman otras expresiones mayores en función de las anteriores.

La especificación anterior puede hacerse también en EBNF, simplificando así alguna de las reglas (concretamente las listas):

java
program ⟶ 'DATA' varDefinition* 'CODE' statement*

varDefinition ⟶ type IDENT ';'

type ⟶ 'float' | 'int'

statement ⟶ 'print' expression ';'
            | expression '=' expression ';'

expression ⟶
     expression ('+' | '-') expression
	| expression ('*' | '/') expression
	| '(' expression ')'
	| IDENT
	| INT_LITERAL
	| FLOAT_LITERAL

Para acabar, nótese que los requisitos sintácticos expresados en el metalenguaje no solo son más precisos, sino que además son mucho más concisos; solo hay que comparar lo que ocupan los requisitos en BNF/EBNF y lo que ocupaban en lenguaje natural en el apartado anterior.

Aclaración sobre la Asignación

Nótese cómo se ha definido la asignación en la solución anterior:

antlr
statement ⟶ expression '=' expression ';'

En realidad, en este lenguaje tan sencillo, hubiera sido más correcto definir la asignación de la siguiente manera, ya que lo único que puede aparecer a la izquierda de una asignación es una variable:

antlr
statement ⟶ ‘IDENT’ '=' expression ';'

El motivo por el que se ha puesto una expresión a la izquierda de la asignación en lugar de una variable es meramente didáctico. Aunque en este lenguaje no hace falta, así es como habrá que hacerlo a poco que el lenguaje se amplíe, ya que, a la izquierda de una asignación, además de una variable, pueden aparecer accesos a arrays, estructuras, etc. Se muestra así cómo sería una versión más real de la representación de una asignación, lo cual permitirá en posteriores capítulos explicar aspectos adicionales.