Entradas para el mes Septiembre dAmerica/Chicago 2006

Creando un analizador semántico

Viernes 29 dAmerica/Chicago Septiembre dAmerica/Chicago 2006 a las 0:52

Entre las funciones de un analizador semántico están las siguientes:

  • Detectar si las variables, constantes y funciones han sido declaradas antes de ser utilizadas.
  • Verificar que las variables, constantes y funciones sean accesibles (visibilidad) desde el ámbito en que son utilizadas.
  • Comprobar que los diferentes identificadores solo hayan sido declarados una vez.
  • Comprobaciones de tipos al evaluar las expresiones. Por ejemplo que no se multiplique un número por una cadena o que la expresión a evaluar en un IF sea del tipo booleano.
  • Verificar que no se intente modificar el valor de una constante.
  • Generar la tabla de símbolos.

El lenguaje de script que estoy desarrollando de momento solo tendrá un ámbito, por lo que no será necesaria la comprobación del ámbito.

Para realizar el análisis semántico utilizaremos una gramática de atributos. Dichos atributos se asociaran tanto a los símbolos terminales como a los no terminales y se propagarán por el árbol sintáctico desde abajo hacia arriba, dando lugar al árbol semántico.
Lo primero que haremos será definir las reglas semánticas, para ello utilizaremos de nuevo la notición BNF a la que añadiremos en pseudocódigo las reglas semánticas.

A continuación se detallan aquellas producciones que constan de reglas semánticas:


10 <DeclaracionVariable> ::= Variable <Tipo> Identificador
	InsertarSimbolo (Variable, Identificador, <Tipo>.Tipo)
11 <Tipo> ::= Numerica
	<Tipo>.Tipo  = Numerica
12 <Tipo> ::= Cadena
	<Tipo>.Tipo  = Cadena
13 <Tipo> ::= Logica
	<Tipo>.Tipo  = Logica
14 <DeclaracionConstante> ::= Constante <Resto_Constante>
	InsertarSimbolo (Constante, Identificador, < Resto_Constante >.Tipo)
18 <Condicional> ::= Si <Expresion> Entonces <Sentencias>  <Resto_Condicional>
	Si <Expresion>.Tipo <> Logica
		Error
21 <Bucle> ::= Mientras <Expresion> Hacer <Sentencias> Fin Mientras
	Si <Expresion>.Tipo <> Logica
		Error
22 <Asignacion_O_LlamadaAMetodo> ::= Identificador <Resto_Asignacion_O_LlamadaAMetodo> 

	Si No Existe (Identificador)
		Error
	Si hijo(1).produccion = 23
		Si es una variable
			Si tipo(identificado) <> hijo(1).tipo
				error
		sino
			Error
	Si hijo(1).produccion = 24
		Recorrer parametros y comprobar que el numero y el tipo de parámetros coincide
23 <Resto_Asignacion_O_LlamadaAMetodo> ::= = <Expresion>
	<Resto_Asignacion_O_LlamadaAMetodo>.Tipo = <Expresion>.Tipo
24 <Resto_Asignacion_O_LlamadaAMetodo> ::= <Parametros>
30 <Expresion> ::= <ExpresionSimple> <Resto_Expresion>
	Si <Resto_Expresion> SeAnula
		<Expresion>.Tipo = <ExpresionSimple>.Tipo
	Sino
		Si <ExpresionSimple>  = <Resto_Expresion>.Tipo
			<Expresion>.Tipo = Logica
		Sino
			Error
31 <Resto_Expresion> ::= <OperadorRelacional> <ExpresionSimple>
	<Resto_Expresion>.Tipo = <ExpresionSimple>.Tipo
32 <Resto_Expresion> ::= ε
39 <ExpresionSimple> ::= <Termino> <Resto_ExpresionSimple>
	Si <Resto_ExpresionSimple>  se anula
		<ExpresionSimple>.Tipo = <Termino>.Tipo
	Sino
		Si <Termino>.Tipo = <Resto_ExpresionSimple>.Tipo
			<ExpresionSimple>.Tipo = <Termino>.Tipo
		Si no
			Error
40 <Resto_ExpresionSimple> ::= <OperadorAditivo> <ExpresionSimple>
	Si <OperadorAditivo> = +
		Si <ExpresionSimple>.Tipo  = Numerica Or <ExpresionSimple>.Tipo = Cadena
			<Resto_ExpresionSimple>.Tipo = <ExpresionSimple>.Tipo
		Sino
			Error
	Si <OperadorAditivo> = -
		Si <ExpresionSimple>.Tipo  = Numerica
			<Resto_ExpresionSimple>.Tipo = <ExpresionSimple>.Tipo
		Sino
			Error
	Si <OperadorAditivo> = O
		Si <ExpresionSimple>.Tipo  = Logica
			<Resto_ExpresionSimple>.Tipo = Logica
		Sino
			Error
41 <Resto_ExpresionSimple> ::= ε
45 <Termino> ::= <Operando> <Resto_Termino>
	Si <Resto_Termino> se anula
		<Termino>.Tipo = <Operando>.Tipo
	Sino
		Si <Operando>.Tipo = <Resto_Termino>.Tipo
			<Termino>.Tipo = <Operando>.Tipo
		Si no
			Error
46 <Resto_Termino> ::= <OperadorMultiplicacion> <Termino>
	Si <OperadorMultiplicacion> = *  Or <OperadorMultiplicacion> = /
		Si <Termino>.Tipo  = Numerica
			<Resto_Termino>.Tipo = Numerica
		Sino
			Error
	Si <OperadorMultiplicacion> = Y
		Si <Termino>.Tipo  = Logica
			<Resto_Termino>.Tipo = Logica
		Sino
			Error
47 <Resto_Termino> ::= ε
51 <Operando> ::= Identificador
	Si Existe(Identificado)
		<Operando>.Tipo = Tipo (Identificador)
	Sino
		Error
52 <Operando> ::= Cte_Numerica
	<Operando>.Tipo = Numerico
53 <Operando> ::= Cte_Cadena
	<Operando>.Tipo = Cadena
54 <Operando> ::= Cte_Logica
	<Operando>.Tipo = Logica
55 <Operando> ::= ( <Expresion> )
	<Operando>.Tipo = Tipo(<Expresion>)

Recorreremos recursivamente el árbol sintáctico en postorden (para cada nodo procesamos recursivamente todos los descendientes primero y luego el nodo). Iremos añadiendo atributos con información al árbol a medida que procesemos nodos. Como el recorrido se realiza en postorden cuando procesemos un nodo ya habremos procesado previamente todos sus descendientes por lo que dispondremos de la información de que nos provean sus atributos.

Añadiremos a la tabla de símbolos todas las constantes y variables que se vayan reconociendo, junto con la información del tipo y el valor (en el caso des la constantes)

La tabla de símbolos será una lista de elementos del tipo símbolo:

VB.NET:
  1. ''' <summary>
  2. ''' Es un simbolo de la tabla de simbolos. Se utiliza en el analizador léxico
  3. ''' </summary>
  4. ''' <remarks></remarks>
  5. Public Class Simbolo
  6.  
  7.     Public Enum ClaseSimbolo
  8.         Variable
  9.         Constante
  10.         Funcion
  11.     End Enum
  12.  
  13.     Private _nombre As String
  14.  
  15.     ''' <summary>
  16.     ''' El nombre del simbolo. Por ejemplo el nombre de una variable tal y como se declara
  17.     ''' </summary>
  18.     ''' <value></value>
  19.     ''' <returns></returns>
  20.     ''' <remarks></remarks>
  21.     Public Property Nombre() As String
  22.         Get
  23.             Return _nombre
  24.         End Get
  25.         Set(ByVal value As String)
  26.             _nombre = value
  27.         End Set
  28.     End Property
  29.  
  30.     Private _clase As ClaseSimbolo
  31.  
  32.     ''' <summary>
  33.     ''' Indica que clase de simbolo es: variable, constante o función
  34.     ''' </summary>
  35.     ''' <value></value>
  36.     ''' <returns></returns>
  37.     ''' <remarks></remarks>
  38.     Public Property Clase() As ClaseSimbolo
  39.         Get
  40.             Return _clase
  41.         End Get
  42.         Set(ByVal value As ClaseSimbolo)
  43.             _clase = value
  44.         End Set
  45.     End Property
  46.  
  47.     Private _tipo As String
  48.  
  49.     ''' <summary>
  50.     ''' Representa el tipo del simbolo: numerica, cadena o logica
  51.     ''' </summary>
  52.     ''' <value></value>
  53.     ''' <returns></returns>
  54.     ''' <remarks></remarks>
  55.     Public Property Tipo() As String
  56.         Get
  57.             Return _tipo
  58.         End Get
  59.         Set(ByVal value As String)
  60.             _tipo = value
  61.         End Set
  62.     End Property
  63.  
  64.     Private _valor As String
  65.  
  66.     ''' <summary>
  67.     ''' Valor del simbolo. Unicamente utilizado por las constantes
  68.     ''' </summary>
  69.     ''' <value></value>
  70.     ''' <returns></returns>
  71.     ''' <remarks></remarks>
  72.     Public Property Valor() As String
  73.         Get
  74.             Return _valor
  75.         End Get
  76.         Set(ByVal value As String)
  77.             _valor = value
  78.         End Set
  79.     End Property
  80.  
  81.     Private _tiposDeLosArgumentos As New List(Of String)
  82.  
  83.     ''' <summary>
  84.     ''' Solo utilizada por los simbolos de tipo función. Es una lista con los tipos de los
  85.     ''' argumentos de la función.
  86.     ''' </summary>
  87.     ''' <value></value>
  88.     ''' <returns></returns>
  89.     ''' <remarks></remarks>
  90.     Public ReadOnly Property TiposDeLosArgumentos() As List(Of String)
  91.         Get
  92.             Return _tiposDeLosArgumentos
  93.         End Get
  94.     End Property
  95.  
  96. End Class

El siguiente script tras pasar por el analizador semántico genera este árbol semántico:

variable numerica j .
j = 1 + 2 * j + 4 .

 


<Elemento Nombre="<SCRIPT>" Produccion="1">
    <Elemento Nombre="<SENTENCIAS>" Produccion="2">
        <Elemento Nombre="<SENTENCIA>" Produccion="5">
            <Elemento Nombre="<DECLARACIONVARIABLE>" Produccion="10">
                <Elemento Nombre="VARIABLE" Palabra="variable" Linea="1" Col="1"></Elemento>
                <Elemento Nombre="<TIPO>" Produccion="11" Tipo="NUMERICA">
                    <Elemento Nombre="NUMERICA" Palabra="numerica" Linea="1" Col="10"></Elemento>
                </Elemento>
                <Elemento Nombre="IDENTIFICADOR" Palabra="j" Linea="1" Col="19"></Elemento>
            </Elemento>
        </Elemento>
        <Elemento Nombre="." Palabra="." Linea="1" Col="21"></Elemento>
        <Elemento Nombre="<RESTO_SENTENCIAS>" Produccion="3">
            <Elemento Nombre="<SENTENCIAS>" Produccion="2">
                <Elemento Nombre="<SENTENCIA>" Produccion="7">
                    <Elemento Nombre="<ASIGNACION_O_LLAMADAAMETODO>" Produccion="22">
                        <Elemento Nombre="IDENTIFICADOR" Palabra="j" Linea="2" Col="1"></Elemento>
                        <Elemento Nombre="<RESTO_ASIGNACION_O_LLAMADAAMETODO>" Produccion="23" Tipo="NUMERICA">
                            <Elemento Nombre="=" Palabra="=" Linea="2" Col="3"></Elemento>
                            <Elemento Nombre="<EXPRESION>" Produccion="30" Tipo="NUMERICA">
                                <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                                    <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                        <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                                            <Elemento Nombre="CTE_NUMERICA" Palabra="1" Linea="2" Col="5"></Elemento>
                                        </Elemento>
                                        <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                                    </Elemento>
                                    <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="40" Tipo="NUMERICA">
                                        <Elemento Nombre="<OPERADORADITIVO>" Produccion="42">
                                            <Elemento Nombre="+" Palabra="+" Linea="2" Col="7"></Elemento>
                                        </Elemento>
                                        <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                                            <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                                <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                                                    <Elemento Nombre="CTE_NUMERICA" Palabra="2" Linea="2" Col="9"></Elemento>
                                                </Elemento>
                                                <Elemento Nombre="<RESTO_TERMINO>" Produccion="46" Tipo="NUMERICA">
                                                    <Elemento Nombre="<OPERADORMULTIPLICACION>" Produccion="48">
                                                        <Elemento Nombre="*" Palabra="*" Linea="2" Col="11"></Elemento>
                                                    </Elemento>
                                                    <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                                        <Elemento Nombre="<OPERANDO>" Produccion="51" Tipo="NUMERICA">
                                                            <Elemento Nombre="IDENTIFICADOR" Palabra="j" Linea="2" Col="13"></Elemento>
                                                        </Elemento>
                                                        <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                                                    </Elemento>
                                                </Elemento>
                                            </Elemento>
                                            <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="40" Tipo="NUMERICA">
                                                <Elemento Nombre="<OPERADORADITIVO>" Produccion="42">
                                                    <Elemento Nombre="+" Palabra="+" Linea="2" Col="15"></Elemento>
                                                </Elemento>
                                                <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                                                    <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                                        <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                                                            <Elemento Nombre="CTE_NUMERICA" Palabra="4" Linea="2" Col="17"></Elemento>
                                                        </Elemento>
                                                        <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                                                    </Elemento>
                                                    <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="41"></Elemento>
                                                </Elemento>
                                            </Elemento>
                                        </Elemento>
                                    </Elemento>
                                </Elemento>
                                <Elemento Nombre="<RESTO_EXPRESION>" Produccion="32"></Elemento>
                            </Elemento>
                        </Elemento>
                    </Elemento>
                </Elemento>
                <Elemento Nombre="." Palabra="." Linea="2" Col="19"></Elemento>
                <Elemento Nombre="<RESTO_SENTENCIAS>" Produccion="4"></Elemento>
            </Elemento>
        </Elemento>
    </Elemento>
    <Elemento Nombre="FIN_FICHERO" Palabra="FIN_SCRIPT" Linea="3" Col="1"></Elemento>
</Elemento

Ejemplos de errores detectados por el analizador semántico, mostrandose primero el script y a continuación el error detectado:

j = 1 + 2 * j + 4 .
ERROR: Identificador no declarado: j en línea 1 Columna 13

variable numerica j .
j = 1 + verdadero .
ERROR: Se esperaba un valor de tipo numérico o cadena tras el operador: + en la línea 2 Columna 7

si "a" = 3 entonces
   j = 4 .
fin si .
ERROR: No es posible realizar la comparación ya que los dos operandos son de tipos distintos. Línea 1 Columna 8

Estado del proyecto a 25/09/2006

Domingo 24 dAmerica/Chicago Septiembre dAmerica/Chicago 2006 a las 23:57

He finalizado el analizador semántico por lo que ya están terminados los tres analizadores (léxico, sintáctico y semántico).

El lenguaje de momento no contempla ámbitos para las variables ni tampoco arrays. Ambas características espero implementarlas en un futuro.

Lo próximo que desarrollaré será el generador de instrucciones, que creará las instrucciones a partir del árbol generado por el analizador semántico y el "tiempo de ejecución". Implementaré también algunas funciones del motor que pueden ser llamadas desde el script, como por ejemplo la escritura en fichero de log y por consola, que me será útil para depurar scripts. Cuando el motor esté más avanzado incluiré nuevas funciones para que puedan ser llamadas desde los scripts.

Durante unos cuantos días no podré dedicarle tiempo al proyecto, por lo que sufrirá un pequeño parón o ralentización temporal. Esto se debe a que me ha surgido un pequeño encargo profesional que tendré que realizar en el poco tiempo libre de que dispongo y que dedicaba al proyecto.

A lo largo de esta semana publicaré un par de artículos sobre el desarrollo del analizador semántico.

Analizador sintáctico (Parte II)

Viernes 22 dAmerica/Chicago Septiembre dAmerica/Chicago 2006 a las 23:58

Este artículo es la continuación de:

Analizador sintáctico (Parte I)

Tras comprobar que cumple la condición LL(1) pasamos a codificar el analizador sintáctico. Para automatizar el reconocimiento de los diferentes elementos creamos la clase producción que encapsulará la información de cada una de las producciones que definimos mediante la notación BNF:

VB.NET:
  1. Public Class Produccion
  2.  
  3.     Dim _parteIzquierda As String
  4.  
  5.     Public ReadOnly Property ParteIzquierda() As String
  6.         Get
  7.             Return _parteIzquierda
  8.         End Get
  9.     End Property
  10.  
  11.     Dim _parteDerecha() As String
  12.  
  13.     Public ReadOnly Property ParteDerecha() As String()
  14.         Get
  15.             Return _parteDerecha
  16.         End Get
  17.     End Property
  18.  
  19.     Dim _simbolosDirectores() As String
  20.  
  21.     Public ReadOnly Property SimbolosDirectores() As String()
  22.         Get
  23.             Return _simbolosDirectores
  24.         End Get
  25.     End Property
  26.  
  27.     Public Sub New(ByVal pParteIzquierda As String, ByVal pParteDerecha As String(), ByVal pSimbolosDirectores() As String)
  28.         _parteIzquierda = pParteIzquierda
  29.         _parteDerecha = pParteDerecha
  30.         _simbolosDirectores = pSimbolosDirectores
  31.     End Sub
  32.  
  33. End Class

El algoritmo del analizador sintáctico es bastante sencillo. Consiste básicamente en ir leyendo las palabras que recibimos del analizador léxico ver si van encajando en un orden valido para el lenguaje. Para ello utilizaremos una pila en la que inicialmente apilaremos el símbolo no terminal que da origen a cualquier secuencia valida, es decir el símbolo <SCRIPT> y leemos la primera palabra que nos ha proporcionado el analizador léxico, esta palabra será el símbolo por adelantado o S.A.

Después realizaremos un bucle del que saldremos cuando se produzca un error o se vacíe la pila y no queden más símbolos por leer de los que nos facilitó el analizador léxico.

Dentro del bucle evaluaremos el símbolo existente en la cima de la pila, si es un símbolo terminal entonces se pueden dar dos casos, que coincida con el símbolo por adelantado que hemos leído en cuyo caso ese símbolo se presenta en un orden correcto y procederemos a desapilar el elemento de la pila y a leer un nuevo S.A. (el siguiente de los entregados por el analizador léxico). En el caso de que no coincidan entonces la palabra no encaja en ninguna secuencia correcta y se trataría de un error sintáctico. Si el símbolo de la cima de la pila es un no terminal buscaremos si existe alguna producción que tenga por parte izquierda ese no terminal y por uno de sus símbolos directores el S.A. Si no existe ninguna producción estaremos ante un error sintáctico y si existe aplicamos la producción, lo cual consiste en desapilar la cima de la pila y apilar todos los elementos de la parte derecha de la producción empezando por el ultimo elemento para que quede el primer elemento en la dima de la pila. Además se añadirán dichos elementos de la parte derecha de la producción en el árbol sintáctico. En este punto finaliza el bucle.

El siguiente script:

variable numerica j .
constante numerica k = 3 .
j = 4 + 7 - 4 * k + 1 .
k = 2 > 4 + 1 .
si X = 3 entonces
j = 4 + 7 - 4 * k + 1 .
fin si .

Producirá las siguientes salidas:


	Aplicada producción: <SCRIPT> ::= <SENTENCIAS> FIN_FICHERO                               S.A. = VARIABLE
	Aplicada producción: <SENTENCIAS> ::= <SENTENCIA> . <RESTO_SENTENCIAS>                               S.A. = VARIABLE
	Aplicada producción: <SENTENCIA> ::= <DECLARACIONVARIABLE>                               S.A. = VARIABLE
	Aplicada producción: <DECLARACIONVARIABLE> ::= VARIABLE <TIPO> IDENTIFICADOR                               S.A. = VARIABLE
Reconocido: VARIABLE
	Aplicada producción: <TIPO> ::= NUMERICA                               S.A. = NUMERICA
Reconocido: NUMERICA
Reconocido: IDENTIFICADOR
Reconocido: .
	Aplicada producción: <RESTO_SENTENCIAS> ::= <SENTENCIAS>                               S.A. = CONSTANTE
	Aplicada producción: <SENTENCIAS> ::= <SENTENCIA> . <RESTO_SENTENCIAS>                               S.A. = CONSTANTE
	Aplicada producción: <SENTENCIA> ::= <DECLARACIONCONSTANTE>                               S.A. = CONSTANTE
	Aplicada producción: <DECLARACIONCONSTANTE> ::= CONSTANTE <RESTO_CONSTANTE>                               S.A. = CONSTANTE
Reconocido: CONSTANTE
	Aplicada producción: <RESTO_CONSTANTE> ::= NUMERICA IDENTIFICADOR = CTE_NUMERICA                               S.A. = NUMERICA
Reconocido: NUMERICA
Reconocido: IDENTIFICADOR
Reconocido: =
Reconocido: CTE_NUMERICA
Reconocido: .
	Aplicada producción: <RESTO_SENTENCIAS> ::= <SENTENCIAS>                               S.A. = IDENTIFICADOR
	Aplicada producción: <SENTENCIAS> ::= <SENTENCIA> . <RESTO_SENTENCIAS>                               S.A. = IDENTIFICADOR
	Aplicada producción: <SENTENCIA> ::= <ASIGNACION_O_LLAMADAAMETODO>                               S.A. = IDENTIFICADOR
	Aplicada producción: <ASIGNACION_O_LLAMADAAMETODO> ::= IDENTIFICADOR <RESTO_ASIGNACION_O_LLAMADAAMETODO>                               S.A. = IDENTIFICADOR
Reconocido: IDENTIFICADOR
	Aplicada producción: <RESTO_ASIGNACION_O_LLAMADAAMETODO> ::= = <EXPRESION>                               S.A. = =
Reconocido: =
	Aplicada producción: <EXPRESION> ::= <EXPRESIONSIMPLE> <RESTO_EXPRESION>                               S.A. = CTE_NUMERICA
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = +
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= <OPERADORADITIVO> <EXPRESIONSIMPLE>                               S.A. = +
	Aplicada producción: <OPERADORADITIVO> ::= +                               S.A. = +
Reconocido: +
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = -
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= <OPERADORADITIVO> <EXPRESIONSIMPLE>                               S.A. = -
	Aplicada producción: <OPERADORADITIVO> ::= -                               S.A. = -
Reconocido: -
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= <OPERADORMULTIPLICACION> <TERMINO>                               S.A. = *
	Aplicada producción: <OPERADORMULTIPLICACION> ::= *                               S.A. = *
Reconocido: *
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = IDENTIFICADOR
	Aplicada producción: <OPERANDO> ::= IDENTIFICADOR                               S.A. = IDENTIFICADOR
Reconocido: IDENTIFICADOR
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = +
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= <OPERADORADITIVO> <EXPRESIONSIMPLE>                               S.A. = +
	Aplicada producción: <OPERADORADITIVO> ::= +                               S.A. = +
Reconocido: +
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = .
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= _VACIO_                               S.A. = .
	Aplicada producción: <RESTO_EXPRESION> ::= _VACIO_                               S.A. = .
Reconocido: .
	Aplicada producción: <RESTO_SENTENCIAS> ::= <SENTENCIAS>                               S.A. = IDENTIFICADOR
	Aplicada producción: <SENTENCIAS> ::= <SENTENCIA> . <RESTO_SENTENCIAS>                               S.A. = IDENTIFICADOR
	Aplicada producción: <SENTENCIA> ::= <ASIGNACION_O_LLAMADAAMETODO>                               S.A. = IDENTIFICADOR
	Aplicada producción: <ASIGNACION_O_LLAMADAAMETODO> ::= IDENTIFICADOR <RESTO_ASIGNACION_O_LLAMADAAMETODO>                               S.A. = IDENTIFICADOR
Reconocido: IDENTIFICADOR
	Aplicada producción: <RESTO_ASIGNACION_O_LLAMADAAMETODO> ::= = <EXPRESION>                               S.A. = =
Reconocido: =
	Aplicada producción: <EXPRESION> ::= <EXPRESIONSIMPLE> <RESTO_EXPRESION>                               S.A. = CTE_NUMERICA
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = >
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= _VACIO_                               S.A. = >
	Aplicada producción: <RESTO_EXPRESION> ::= <OPERADORRELACIONAL> <EXPRESIONSIMPLE>                               S.A. = >
	Aplicada producción: <OPERADORRELACIONAL> ::= >                               S.A. = >
Reconocido: >
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = +
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= <OPERADORADITIVO> <EXPRESIONSIMPLE>                               S.A. = +
	Aplicada producción: <OPERADORADITIVO> ::= +                               S.A. = +
Reconocido: +
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = .
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= _VACIO_                               S.A. = .
Reconocido: .
	Aplicada producción: <RESTO_SENTENCIAS> ::= <SENTENCIAS>                               S.A. = SI
	Aplicada producción: <SENTENCIAS> ::= <SENTENCIA> . <RESTO_SENTENCIAS>                               S.A. = SI
	Aplicada producción: <SENTENCIA> ::= <CONDICIONAL>                               S.A. = SI
	Aplicada producción: <CONDICIONAL> ::= SI <EXPRESION> ENTONCES <SENTENCIAS> <RESTO_CONDICIONAL>                               S.A. = SI
Reconocido: SI
	Aplicada producción: <EXPRESION> ::= <EXPRESIONSIMPLE> <RESTO_EXPRESION>                               S.A. = IDENTIFICADOR
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = IDENTIFICADOR
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = IDENTIFICADOR
	Aplicada producción: <OPERANDO> ::= IDENTIFICADOR                               S.A. = IDENTIFICADOR
Reconocido: IDENTIFICADOR
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = =
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= _VACIO_                               S.A. = =
	Aplicada producción: <RESTO_EXPRESION> ::= <OPERADORRELACIONAL> <EXPRESIONSIMPLE>                               S.A. = =
	Aplicada producción: <OPERADORRELACIONAL> ::= =                               S.A. = =
Reconocido: =
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = ENTONCES
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= _VACIO_                               S.A. = ENTONCES
Reconocido: ENTONCES
	Aplicada producción: <SENTENCIAS> ::= <SENTENCIA> . <RESTO_SENTENCIAS>                               S.A. = IDENTIFICADOR
	Aplicada producción: <SENTENCIA> ::= <ASIGNACION_O_LLAMADAAMETODO>                               S.A. = IDENTIFICADOR
	Aplicada producción: <ASIGNACION_O_LLAMADAAMETODO> ::= IDENTIFICADOR <RESTO_ASIGNACION_O_LLAMADAAMETODO>                               S.A. = IDENTIFICADOR
Reconocido: IDENTIFICADOR
	Aplicada producción: <RESTO_ASIGNACION_O_LLAMADAAMETODO> ::= = <EXPRESION>                               S.A. = =
Reconocido: =
	Aplicada producción: <EXPRESION> ::= <EXPRESIONSIMPLE> <RESTO_EXPRESION>                               S.A. = CTE_NUMERICA
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = +
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= <OPERADORADITIVO> <EXPRESIONSIMPLE>                               S.A. = +
	Aplicada producción: <OPERADORADITIVO> ::= +                               S.A. = +
Reconocido: +
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = -
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= <OPERADORADITIVO> <EXPRESIONSIMPLE>                               S.A. = -
	Aplicada producción: <OPERADORADITIVO> ::= -                               S.A. = -
Reconocido: -
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= <OPERADORMULTIPLICACION> <TERMINO>                               S.A. = *
	Aplicada producción: <OPERADORMULTIPLICACION> ::= *                               S.A. = *
Reconocido: *
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = IDENTIFICADOR
	Aplicada producción: <OPERANDO> ::= IDENTIFICADOR                               S.A. = IDENTIFICADOR
Reconocido: IDENTIFICADOR
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = +
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= <OPERADORADITIVO> <EXPRESIONSIMPLE>                               S.A. = +
	Aplicada producción: <OPERADORADITIVO> ::= +                               S.A. = +
Reconocido: +
	Aplicada producción: <EXPRESIONSIMPLE> ::= <TERMINO> <RESTO_EXPRESIONSIMPLE>                               S.A. = CTE_NUMERICA
	Aplicada producción: <TERMINO> ::= <OPERANDO> <RESTO_TERMINO>                               S.A. = CTE_NUMERICA
	Aplicada producción: <OPERANDO> ::= CTE_NUMERICA                               S.A. = CTE_NUMERICA
Reconocido: CTE_NUMERICA
	Aplicada producción: <RESTO_TERMINO> ::= _VACIO_                               S.A. = .
	Aplicada producción: <RESTO_EXPRESIONSIMPLE> ::= _VACIO_                               S.A. = .
	Aplicada producción: <RESTO_EXPRESION> ::= _VACIO_                               S.A. = .
Reconocido: .
	Aplicada producción: <RESTO_SENTENCIAS> ::= _VACIO_                               S.A. = FIN
	Aplicada producción: <RESTO_CONDICIONAL> ::= FIN SI                               S.A. = FIN
Reconocido: FIN
Reconocido: SI
Reconocido: .
	Aplicada producción: <RESTO_SENTENCIAS> ::= _VACIO_                               S.A. = FIN_FICHERO
Reconocido: FIN_FICHERO

 

Y el siguiente árbol sintáctico:

 


<Elemento Nombre="<SCRIPT>" Produccion="1">
  <Elemento Nombre="<SENTENCIAS>" Produccion="2">
    <Elemento Nombre="<SENTENCIA>" Produccion="7">
      <Elemento Nombre="<ASIGNACION_O_LLAMADAAMETODO>" Produccion="22">
        <Elemento Nombre="IDENTIFICADOR" Palabra="miFuncion" Linea="1" Col="1"></Elemento>
        <Elemento Nombre="<RESTO_ASIGNACION_O_LLAMADAAMETODO>" Produccion="24">
          <Elemento Nombre="<PARAMETROS>" Produccion="26"></Elemento>
        </Elemento>
      </Elemento>
    </Elemento>
    <Elemento Nombre="." Palabra="." Linea="1" Col="11"></Elemento>
    <Elemento Nombre="<RESTO_SENTENCIAS>" Produccion="3">
      <Elemento Nombre="<SENTENCIAS>" Produccion="2">
        <Elemento Nombre="<SENTENCIA>" Produccion="7">
          <Elemento Nombre="<ASIGNACION_O_LLAMADAAMETODO>" Produccion="22">
            <Elemento Nombre="IDENTIFICADOR" Palabra="miFuncion" Linea="2" Col="1"></Elemento>
            <Elemento Nombre="<RESTO_ASIGNACION_O_LLAMADAAMETODO>" Produccion="24">
              <Elemento Nombre="<PARAMETROS>" Produccion="25">
                <Elemento Nombre="<UNOOMASPARAMETROS>" Produccion="27">
                  <Elemento Nombre="<EXPRESION>" Produccion="30" Tipo="NUMERICA">
                    <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                      <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                        <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                          <Elemento Nombre="CTE_NUMERICA" Palabra="1" Linea="2" Col="11"></Elemento>
                        </Elemento>
                        <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                      </Elemento>
                      <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="41"></Elemento>
                    </Elemento>
                    <Elemento Nombre="<RESTO_EXPRESION>" Produccion="32"></Elemento>
                  </Elemento>
                  <Elemento Nombre="<RESTO_UNOOMASPARAMETROS>" Produccion="28">
                    <Elemento Nombre="," Palabra="," Linea="2" Col="13"></Elemento>
                    <Elemento Nombre="<UNOOMASPARAMETROS>" Produccion="27">
                      <Elemento Nombre="<EXPRESION>" Produccion="30" Tipo="CADENA">
                        <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="CADENA">
                          <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="CADENA">
                            <Elemento Nombre="<OPERANDO>" Produccion="53" Tipo="CADENA">
                              <Elemento Nombre="CTE_CADENA" Palabra=""a"" Linea="2" Col="15"></Elemento>
                            </Elemento>
                            <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                          </Elemento>
                          <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="41"></Elemento>
                        </Elemento>
                        <Elemento Nombre="<RESTO_EXPRESION>" Produccion="32"></Elemento>
                      </Elemento>
                      <Elemento Nombre="<RESTO_UNOOMASPARAMETROS>" Produccion="28">
                        <Elemento Nombre="," Palabra="," Linea="2" Col="19"></Elemento>
                        <Elemento Nombre="<UNOOMASPARAMETROS>" Produccion="27">
                          <Elemento Nombre="<EXPRESION>" Produccion="30" Tipo="NUMERICA">
                            <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                              <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                                  <Elemento Nombre="CTE_NUMERICA" Palabra="2" Linea="2" Col="21"></Elemento>
                                </Elemento>
                                <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                              </Elemento>
                              <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="41"></Elemento>
                            </Elemento>
                            <Elemento Nombre="<RESTO_EXPRESION>" Produccion="32"></Elemento>
                          </Elemento>
                          <Elemento Nombre="<RESTO_UNOOMASPARAMETROS>" Produccion="28">
                            <Elemento Nombre="," Palabra="," Linea="2" Col="23"></Elemento>
                            <Elemento Nombre="<UNOOMASPARAMETROS>" Produccion="27">
                              <Elemento Nombre="<EXPRESION>" Produccion="30" Tipo="CADENA">
                                <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="CADENA">
                                  <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="CADENA">
                                    <Elemento Nombre="<OPERANDO>" Produccion="53" Tipo="CADENA">
                                      <Elemento Nombre="CTE_CADENA" Palabra=""b"" Linea="2" Col="25"></Elemento>
                                    </Elemento>
                                    <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                                  </Elemento>
                                  <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="41"></Elemento>
                                </Elemento>
                                <Elemento Nombre="<RESTO_EXPRESION>" Produccion="32"></Elemento>
                              </Elemento>
                              <Elemento Nombre="<RESTO_UNOOMASPARAMETROS>" Produccion="29"></Elemento>
                            </Elemento>
                          </Elemento>
                        </Elemento>
                      </Elemento>
                    </Elemento>
                  </Elemento>
                </Elemento>
              </Elemento>
            </Elemento>
          </Elemento>
        </Elemento>
        <Elemento Nombre="." Palabra="." Linea="2" Col="29"></Elemento>
        <Elemento Nombre="<RESTO_SENTENCIAS>" Produccion="3">
          <Elemento Nombre="<SENTENCIAS>" Produccion="2">
            <Elemento Nombre="<SENTENCIA>" Produccion="5">
              <Elemento Nombre="<DECLARACIONVARIABLE>" Produccion="10">
                <Elemento Nombre="VARIABLE" Palabra="variable" Linea="3" Col="1"></Elemento>
                <Elemento Nombre="<TIPO>" Produccion="11" Tipo="NUMERICA">
                  <Elemento Nombre="NUMERICA" Palabra="numerica" Linea="3" Col="10"></Elemento>
                </Elemento>
                <Elemento Nombre="IDENTIFICADOR" Palabra="j" Linea="3" Col="19"></Elemento>
              </Elemento>
            </Elemento>
            <Elemento Nombre="." Palabra="." Linea="3" Col="21"></Elemento>
            <Elemento Nombre="<RESTO_SENTENCIAS>" Produccion="3">
              <Elemento Nombre="<SENTENCIAS>" Produccion="2">
                <Elemento Nombre="<SENTENCIA>" Produccion="6">
                  <Elemento Nombre="<DECLARACIONCONSTANTE>" Produccion="14">
                    <Elemento Nombre="CONSTANTE" Palabra="constante" Linea="4" Col="1"></Elemento>
                    <Elemento Nombre="<RESTO_CONSTANTE>" Produccion="15">
                      <Elemento Nombre="NUMERICA" Palabra="numerica" Linea="4" Col="11"></Elemento>
                      <Elemento Nombre="IDENTIFICADOR" Palabra="k" Linea="4" Col="20"></Elemento>
                      <Elemento Nombre="=" Palabra="=" Linea="4" Col="22"></Elemento>
                      <Elemento Nombre="CTE_NUMERICA" Palabra="3" Linea="4" Col="24"></Elemento>
                    </Elemento>
                  </Elemento>
                </Elemento>
                <Elemento Nombre="." Palabra="." Linea="4" Col="26"></Elemento>
                <Elemento Nombre="<RESTO_SENTENCIAS>" Produccion="3">
                  <Elemento Nombre="<SENTENCIAS>" Produccion="2">
                    <Elemento Nombre="<SENTENCIA>" Produccion="7">
                      <Elemento Nombre="<ASIGNACION_O_LLAMADAAMETODO>" Produccion="22">
                        <Elemento Nombre="IDENTIFICADOR" Palabra="j" Linea="5" Col="1"></Elemento>
                        <Elemento Nombre="<RESTO_ASIGNACION_O_LLAMADAAMETODO>" Produccion="23" Tipo="NUMERICA">
                          <Elemento Nombre="=" Palabra="=" Linea="5" Col="3"></Elemento>
                          <Elemento Nombre="<EXPRESION>" Produccion="30" Tipo="NUMERICA">
                            <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                              <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                                  <Elemento Nombre="CTE_NUMERICA" Palabra="4" Linea="5" Col="5"></Elemento>
                                </Elemento>
                                <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                              </Elemento>
                              <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="40" Tipo="NUMERICA">
                                <Elemento Nombre="<OPERADORADITIVO>" Produccion="42">
                                  <Elemento Nombre="+" Palabra="+" Linea="5" Col="7"></Elemento>
                                </Elemento>
                                <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                                  <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                    <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                                      <Elemento Nombre="CTE_NUMERICA" Palabra="7" Linea="5" Col="9"></Elemento>
                                    </Elemento>
                                    <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                                  </Elemento>
                                  <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="40" Tipo="NUMERICA">
                                    <Elemento Nombre="<OPERADORADITIVO>" Produccion="43">
                                      <Elemento Nombre="-" Palabra="-" Linea="5" Col="11"></Elemento>
                                    </Elemento>
                                    <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                                      <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                        <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                                          <Elemento Nombre="CTE_NUMERICA" Palabra="4" Linea="5" Col="13"></Elemento>
                                        </Elemento>
                                        <Elemento Nombre="<RESTO_TERMINO>" Produccion="46" Tipo="NUMERICA">
                                          <Elemento Nombre="<OPERADORMULTIPLICACION>" Produccion="48">
                                            <Elemento Nombre="*" Palabra="*" Linea="5" Col="15"></Elemento>
                                          </Elemento>
                                          <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                            <Elemento Nombre="<OPERANDO>" Produccion="51" Tipo="NUMERICA">
                                              <Elemento Nombre="IDENTIFICADOR" Palabra="k" Linea="5" Col="17"></Elemento>
                                            </Elemento>
                                            <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                                          </Elemento>
                                        </Elemento>
                                      </Elemento>
                                      <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="40" Tipo="NUMERICA">
                                        <Elemento Nombre="<OPERADORADITIVO>" Produccion="42">
                                          <Elemento Nombre="+" Palabra="+" Linea="5" Col="19"></Elemento>
                                        </Elemento>
                                        <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                                          <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                            <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                                              <Elemento Nombre="CTE_NUMERICA" Palabra="1" Linea="5" Col="21"></Elemento>
                                            </Elemento>
                                            <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                                          </Elemento>
                                          <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="41"></Elemento>
                                        </Elemento>
                                      </Elemento>
                                    </Elemento>
                                  </Elemento>
                                </Elemento>
                              </Elemento>
                            </Elemento>
                            <Elemento Nombre="<RESTO_EXPRESION>" Produccion="32"></Elemento>
                          </Elemento>
                        </Elemento>
                      </Elemento>
                    </Elemento>
                    <Elemento Nombre="." Palabra="." Linea="5" Col="23"></Elemento>
                    <Elemento Nombre="<RESTO_SENTENCIAS>" Produccion="3">
                      <Elemento Nombre="<SENTENCIAS>" Produccion="2">
                        <Elemento Nombre="<SENTENCIA>" Produccion="7">
                          <Elemento Nombre="<ASIGNACION_O_LLAMADAAMETODO>" Produccion="22">
                            <Elemento Nombre="IDENTIFICADOR" Palabra="k" Linea="6" Col="1"></Elemento>
                            <Elemento Nombre="<RESTO_ASIGNACION_O_LLAMADAAMETODO>" Produccion="23" Tipo="LOGICA">
                              <Elemento Nombre="=" Palabra="=" Linea="6" Col="3"></Elemento>
                              <Elemento Nombre="<EXPRESION>" Produccion="30" Tipo="LOGICA">
                                <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                                  <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                    <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                                      <Elemento Nombre="CTE_NUMERICA" Palabra="2" Linea="6" Col="5"></Elemento>
                                    </Elemento>
                                    <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                                  </Elemento>
                                  <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="41"></Elemento>
                                </Elemento>
                                <Elemento Nombre="<RESTO_EXPRESION>" Produccion="31" Tipo="NUMERICA">
                                  <Elemento Nombre="<OPERADORRELACIONAL>" Produccion="34">
                                    <Elemento Nombre=">" Palabra=">" Linea="6" Col="7"></Elemento>
                                  </Elemento>
                                  <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                                    <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                      <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                                        <Elemento Nombre="CTE_NUMERICA" Palabra="4" Linea="6" Col="9"></Elemento>
                                      </Elemento>
                                      <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                                    </Elemento>
                                    <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="40" Tipo="NUMERICA">
                                      <Elemento Nombre="<OPERADORADITIVO>" Produccion="42">
                                        <Elemento Nombre="+" Palabra="+" Linea="6" Col="11"></Elemento>
                                      </Elemento>
                                      <Elemento Nombre="<EXPRESIONSIMPLE>" Produccion="39" Tipo="NUMERICA">
                                        <Elemento Nombre="<TERMINO>" Produccion="45" Tipo="NUMERICA">
                                          <Elemento Nombre="<OPERANDO>" Produccion="52" Tipo="NUMERICA">
                                            <Elemento Nombre="CTE_NUMERICA" Palabra="1" Linea="6" Col="13"></Elemento>
                                          </Elemento>
                                          <Elemento Nombre="<RESTO_TERMINO>" Produccion="47"></Elemento>
                                        </Elemento>
                                        <Elemento Nombre="<RESTO_EXPRESIONSIMPLE>" Produccion="41"></Elemento>
                                      </Elemento>
                                    </Elemento>
                                  </Elemento>
                                </Elemento>
                              </Elemento>
                            </Elemento>
                          </Elemento>
                        </Elemento>
                        <Elemento Nombre="." Palabra="." Linea="6" Col="15"></Elemento>
                        <Elemento Nombre="<RESTO_SENTENCIAS>" Produccion="4"></Elemento>
                      </Elemento>
                    </Elemento>
                  </Elemento>
                </Elemento>
              </Elemento>
            </Elemento>
          </Elemento>
        </Elemento>
      </Elemento>
    </Elemento>
  </Elemento>
  <Elemento Nombre="FIN_FICHERO" Palabra="FIN_SCRIPT" Linea="7" Col="1"></Elemento>
</Elemento>

Para el siguiente script que contiene un error

variable numerica j .
constante numerica k = valor .

Se obtiene la siguiente salida:


	Aplicada producción: <SCRIPT> ::= <SENTENCIAS> FIN_FICHERO                               S.A. = VARIABLE
	Aplicada producción: <SENTENCIAS> ::= <SENTENCIA> . <RESTO_SENTENCIAS>                               S.A. = VARIABLE
	Aplicada producción: <SENTENCIA> ::= <DECLARACIONVARIABLE>                               S.A. = VARIABLE
	Aplicada producción: <DECLARACIONVARIABLE> ::= VARIABLE <TIPO> IDENTIFICADOR                               S.A. = VARIABLE
Reconocido: VARIABLE
	Aplicada producción: <TIPO> ::= NUMERICA                               S.A. = NUMERICA
Reconocido: NUMERICA
Reconocido: IDENTIFICADOR
Reconocido: .
	Aplicada producción: <RESTO_SENTENCIAS> ::= <SENTENCIAS>                               S.A. = CONSTANTE
	Aplicada producción: <SENTENCIAS> ::= <SENTENCIA> . <RESTO_SENTENCIAS>                               S.A. = CONSTANTE
	Aplicada producción: <SENTENCIA> ::= <DECLARACIONCONSTANTE>                               S.A. = CONSTANTE
	Aplicada producción: <DECLARACIONCONSTANTE> ::= CONSTANTE <RESTO_CONSTANTE>                               S.A. = CONSTANTE
Reconocido: CONSTANTE
	Aplicada producción: <RESTO_CONSTANTE> ::= NUMERICA IDENTIFICADOR = CTE_NUMERICA                               S.A. = NUMERICA
Reconocido: NUMERICA
Reconocido: IDENTIFICADOR
Reconocido: =
Se esperaba la palabra 'CTE_NUMERICA' y ha llegado la palabra 'valor' Linea: 2 Columna: 24

 

Primera parte de este artículo:

Analizador sintáctico (Parte I)

 

Analizador sintáctico (Parte I)

Miércoles 20 dAmerica/Chicago Septiembre dAmerica/Chicago 2006 a las 23:59

El analizador sintáctico recibe los tokens o palabras generadas por el analizador léxico y determina si la secuencia u orden que presentan es correcta y permitida por el lenguaje. La salida que generará será el árbol sintáctico.

Lo primero que tenemos que hacer es determinar la sintaxis del lenguaje y expresarla formalmente en notación BNF. Esta tarea es bastante sencilla.


Script ::= <Sentencias> FinFichero
<Sentencias> ::= <Sentencia> . <Sentencias>
		| <Sentencia>
<Sentencia> ::= <DeclaracionVariable>
		| <DeclaracionConstante>
		| <Asignacion>
		| <Condicional>
		| <Bucle>
		| <LlamadaAMetodo>
<DeclaracionVariable> ::= Variable <Tipo> Identificador
<Tipo> ::= Numerica
		| Cadena
		| Logica
<DeclaracionConstante> ::= Constante Numerica Identificador = Cte_Numerica
		| Constante Cadena Identificador = Cte_Cadena
		| Constante Logica Identificador = Cte_Logica
<Asignacion> ::= Identificador = <Expresion>
<Condicional> ::= Si <Expresion> Entonces <Sentencias>	<RestoCondicional>
<RestoCondicional> ::= Sino <Sentencias> Fin Si
		| Fin Si
<Bucle> ::= Mientras <Expresion> Hacer <Sentencias> Fin Mientras
<LlamadaAMetodo> :: = Identificador <Parametros>
<Parametros> ::= < UnoOMasParametros >
		| ε
<UnoOMasParametros>::=  <Expresion> , <UnoOMasParametros>
		| < Expresion >
<Expresion> ::= <ExpresionSimple> <OperadorRelacional> <ExpresionSimple>
		| <ExpresionSimple>
<OperadorRelacional> ::= < | > | <= | >= | = | !=
<ExpresionSimple> ::= < ExpresionSimple > <OperadorAditivo> < Termino>
		| <Termino>
<OperadorAditivo> ::= + | - | O
<Termino> ::= <Termino> <OperdoraMultiplicacion> <Operando>
		| <Operando>
<OperadorMultiplicacion> ::= * | / | Y
<Operando> ::= Identificador
		| Cte_Numerica
		| Cte_Cadena
		| Cte_Logica
		| ( <Expresion> )

Vamos a imponer que nuestra definición del lenguaje cumpla la condición LL(1), lo cual implica que a partir de un determinado símbolo no terminal solo existe una producción que se puede aplicar. Para lo cual hay que eliminar las ambigüedades, la recursividad inmediata por la izquierda y los prefijos comunes. Esto es algo más complicado y nos puede dar algún quebradero de cabeza.

1. <Sentencia> ::= <Asignacion>
2. <Sentencia> ::= <LLamadaAMetodo>
3. <Asignacion> ::= Identificador = <Expresion>
4. <LLamadaAMetodo> ::= Identificador <Parametros>

En este ejemplo el lenguaje no cumpliría la condición LL(1) ya que si el símbolo que leemos es un identificador se podrían aplicar tanto la producción uno como la dos.

Para comprobar que cumple la condición LL(1) hemos de calcular los símbolos directores, es decir aquellos símbolos terminales que nos guiarán para elegir una determinada producción entre todas aquellas que tengan la misma parte izquierda. De tal forma que cuando tengamos un determinado no terminal y leamos un símbolo por adelantado solo exista una producción que tenga el no terminal por parte izquierda y el símbolo por adelantado como símbolo director. En el ejemplo anterior tendríamos como símbolo director de todas las producciones el no terminal "Identificador", por lo tanto si tenemos el no terminal <Sentencia> y leemos el símbolo "Identificador" no podríamos decantarnos por ninguna de las dos producciones (la uno o la dos).

El calculo de los directores es una tarea sumamente tediosa y es fácil cometer algún error. Numeramos las producciones para poder identificarlas más fácilmente.


1 <Script> ::= <Sentencias> FinFichero
	Dir = Inic(Sentencias) = Inic(Sentencia) = Inic(DeclaracionVariable) U Inic(DeclaracionConstante) U Inic(Asignacion_O_LlamadaAMetodo) U Inic(Condicional) U Inic(Bucle) = Variable Constante Identificador Si Mientras
2 <Sentencias> ::= <Sentencia> . <Resto_Sentencias>
	Dir = Inic(Sentencia) = Inic(DeclaracionVariable) U Inic(DeclaracionConstante) U Inic(Asignacion_O_LlamadaAMetodo) U Inic(Condicional) U Inic(Bucle) = Variable Constante Identificador Si Mientras
3 <Resto_Sentencias> ::= <Sentencias>
	Dir = Inic (sentencias) = Variable Constante Identificador Si Mientras
4 <Resto_Sentencias> ::= ε
	Dir = Seg(Resto_Sentencias) = Seg(Sentencias) = FinFichero U Fin U Sino U Seg(Resto_Sentencias) = FinFichero Fin Sino
5 <Sentencia> ::= <DeclaracionVariable>
	Dir = Variable
6 <Sentencia> ::= <DeclaracionConstante>
	Dir = Constante
7 <Sentencia> ::= <Asignacion_O_LlamadaAMetodo>
	Dir = Identificador
8 <Sentencia> ::= <Condicional>
	Dir = Si
9 <Sentencia> ::= <Bucle>
	Dir = Mientras
10 <DeclaracionVariable> ::= Variable <Tipo> Identificador
	Dir = Variable
11 <Tipo> ::= Numerica
	Dir = Numerica
12 <Tipo> ::= Cadena
	Dir = Cadena
13 <Tipo> ::= Logica
	Dir = Logica
14 <DeclaracionConstante> ::= Constante <Resto_Constante>
	Dir = Constante
15 <Resto_Constante> ::= Numerica Identificador = Cte_Numerica
	Dir = Numerica
16 <Resto_Constante> ::= Cadena Identificador = Cte_Cadena
	Dir = Cadena
17 <Resto_Constante> ::= Logica Identificador = Cte_Logica
	Dir = Logica
18 <Condicional> ::= Si <Expresion> Entonces <Sentencias>  <Resto_Condicional>
	Dir = Si
19 <Resto_Condicional> ::= Sino <Sentencias> Fin Si
	Dir = Sino
20 <Resto_Condicional> ::= Fin Si
	Dir = Fin
21 <Bucle> ::= Mientras <Expresion> Hacer <Sentencias> Fin Mientras
	Dir = Mientras
22 <Asignacion_O_LlamadaAMetodo> ::= Identificador						<Resto_Asignacion_O_LlamadaAMetodo>
	Dir = Identificador
23 <Resto_Asignacion_O_LlamadaAMetodo> ::= = <Expresion>
	Dir = =
24 <Resto_Asignacion_O_LlamadaAMetodo> ::= <Parametros>
	Dir = Inic(UnoOMasParametros) U Seg(Parametros) = Inic (Expresion) U Seg(Resto_Asignacion_O_LlamadaAMetodo) = Inic(ExpresionSimple) U Seg(Asignacion_O_LlamadaAMetodo) = Inic(Termino) U Seg(Sentencia) = Inic(Operando)  U . = Identificador Cte_Numerica Cte_Cadena Cte_Logica ( .
25 <Parametros> ::= <UnoOMasParametros>
	Dir = Inic (UnoOMasParametros) = Inic(Expresion) = Inic(ExpresionSimple) = Inic(Termino) = Inic(Operando)  = Identificador Cte_Numerica Cte_Cadena Cte_Logica (
26 <Parametros> ::= ε
	Dir = Seg(Parametros) = Seg(Resto_Asignacion_O_LlamadaAMetodo) = Seg(Asignacion_O_LlamadaAMetodo) = Seg(Sentencia) = .
27 <UnoOMasParametros>::=  <Expresion> <Resto_UnoOMasParametros>
	Dir = Inic(Expresion) = Inic(ExpresionSimple) = Inic(Termino) = Inic(Operando)  = Identificador Cte_Numerica Cte_Cadena Cte_Logica (
28 <Resto_UnoOMasParametros>::=  , <UnoOMasParametros>
	Dir = ,
29 <Resto_UnoOMasParametros>::= ε
	Dir = Seg(Resto_UnoOMasParametros) = Seg(UnoOMasParametros) = Seg(Parametros) = Seg (Resto_Asignacion_O_LlamadaAMetodo) = Seg(Asignacion_O_LlamadaAMetodo) = Seg(Sentencia) = .
30 <Expresion> ::= <ExpresionSimple> <Resto_Expresion>
	Dir = Inic(ExpresionSimple) = Inic(Termino) = Inic(Operando)  = Identificador Cte_Numerica Cte_Cadena Cte_Logica (
31 <Resto_Expresion> ::= <OperadorRelacional> <ExpresionSimple>
	Dir = Inic(OperadorRelacional) = <  >  <=  >=  =  !=
32 <Resto_Expresion> ::= ε
	Dir = Seg(Expresion) = Entonces U Hacer U ) U , U Seg(Resto_Asignacion_O_LlamadaAMetodo) = Entonces U Hacer U ) U Seg(Asignacion_O_LlamadaAMetodo) = Entonces U Hacer U ) U Seg(Sentencia) = Entonces Hacer  )  ,  .
33 <OperadorRelacional> ::= <
	Dir = <
34 <OperadorRelacional> ::= >
	Dir = >
35 <OperadorRelacional> ::= <=
	Dir = <=
36 <OperadorRelacional> ::= >=
	Dir = >=
37 <OperadorRelacional> ::= =
	Dir = =
38 <OperadorRelacional> ::=!=
	Dir = !=
39 <ExpresionSimple> ::= <Termino> <Resto_ExpresionSimple>
	Dir = Inic(Termino) = Inic(Operando)  = Identificador Cte_Numerica Cte_Cadena Cte_Logica (
40 <Resto_ExpresionSimple> ::= <OperadorAditivo> <ExpresionSimple>
	Dir = + - O
41 <Resto_ExpresionSimple> ::= ε
	Dir = Seg(Resto_ExpresionSimple) = Seg(ExpresionSimple) = Inic(Resto_Expresion) U Seg(Expresion) U Seg(Resto_Expresion) U Seg(Resto_ExpresionSimple) = Inic(OperadorRelacional) U Entonces U Hacer U ) U , U . U Seg(Resto_Asignacion_O_LlamadaAMetodo) U Seg(Expresion) =
<  >  <=  >=  =  != U Entonces U Hacer . U )
42 <OperadorAditivo> ::= +
	Dir =  +
43 <OperadorAditivo> ::=  -
	Dir =  -
44 <OperadorAditivo> ::=  O
	Dir = O
45 <Termino> ::= <Operando> <Resto_Termino>
	Dir = Inic(Operando)  = Identificador Cte_Numerica Cte_Cadena Cte_Logica (
46 <Resto_Termino> ::= <OperadorMultiplicacion> <Termino>
	Dir = * / Y
47 <Resto_Termino> ::= ε
	Dir = Seg(Resto_Termino) = Seg(Termino) = Inic (Resto_ExpresionSimple) U Seg(ExpresionSimple) = Inic(OperadorAditivo) U Inic(Resto_Expresion) U Seg(Expresion) U Seg(Resto_Expresion) U Seg(Resto_ExpresionSimple) = + - O U Inic(OperadorRelacional) U Entonces U Hacer U . U , U Seg(Resto_Asignacion_O_LlamadaAMetodo) U Seg(Expresion) = + - O U
<  >  <=  >=  =  != U Entonces U Hacer U . U , U  ) U Seg(Sentencia) = + - O U
<  >  <=  >=  =  != U Entonces U Hacer U . U ,U ) U Inic(Resto_Sentencias) = + - O U <  >  <=  >=  =  != U Entonces U Hacer U . U , U )
48 <OperadorMultiplicacion> ::= *
	Dir = *
49 <OperadorMultiplicacion> ::= /
	Dir = /
50 <OperadorMultiplicacion> ::= Y
	Dir = Y
51 <Operando> ::= Identificador
	Dir = Identificador
52 <Operando> ::= Cte_Numerica
	Dir = Cte_Numerica
53 <Operando> ::= Cte_Cadena
	Dir = Cte_Cadena
54 <Operando> ::= Cte_Logica
	Dir = Cte_Logica
55 <Operando> ::= ( <Expresion> )
	Dir = (

Continuación
Analizador sintáctico (Parte II)

Añadida descarga: Visor XML

Domingo 17 dAmerica/Chicago Septiembre dAmerica/Chicago 2006 a las 23:58

He añadido en la sección de descargas el código fuente completo del Visor XML así como el ejecutable del mismo.

Esta herramienta me ha sido de gran utilidad para la depuración del árbol sintáctico y semántico generados por los respectivos analizadores.

Hace tiempo desarrollé un addin para el Visual Studio 2003 que incorporaba una nueva ventana de inspección al IDE que permitía explorar variables que tuvieran XML (tanto en una variable de tipo string como XMLDocument) y ver su contenido con esta herramienta y realizar búsquedas en el XML.

 

Creando un visor de XML (Parte II)

Miércoles 13 dAmerica/Chicago Septiembre dAmerica/Chicago 2006 a las 23:59

Este artículo es la continuación de:

Creando un visor de XML (Parte I)

POBLANDO EL TREEVIEW:

El proceso es muy similar al descrito anteriormente, salvo que ahora en vez de transformar el árbol en una cadena de texto formateada, se irán incluyendo sus nodos jerárquicamente en un TreeView.

Para poblar el TreeView también nos basaremos en dos funciones, una para inicializar las variables y cargar el documento xml, y otra que será llamada de forma recursiva.

VB.NET:
  1. Private Sub MostrarArbol(ByVal consultar As Boolean)
  2.         Dim arbol As New Xml.XmlDocument
  3.         Dim nodoRaiz As TreeNode
  4.         Dim atr As Xml.XmlAttribute
  5.  
  6.         'Utilizados solo para hacer la consulta
  7.         Dim nodosSeleccionados As Xml.XmlNodeList
  8.  
  9.         Try
  10.             arbol.LoadXml(rtxtXML.Text)
  11.  
  12.             trvXML.Nodes.Clear()
  13.             nodoRaiz = New TreeNode(arbol.DocumentElement.Name)
  14.             For Each atr In arbol.DocumentElement.Attributes
  15.                 nodoRaiz.Text &= "   " & atr.Name & "=" & atr.Value
  16.             Next
  17.             trvXML.Nodes.Add(nodoRaiz)
  18.  
  19.             If consultar Then
  20.                 nodosSeleccionados = arbol.SelectNodes(txtConsulta.Text)
  21.                 If estaSeleccionado(arbol.DocumentElement, nodosSeleccionados) Then
  22.                     nodoRaiz.ForeColor = Color.Blue
  23.                     nodoRaiz.NodeFont = fuenteNegritaArbol
  24.                 End If
  25.                 AnadirNodosAArbol(nodoRaiz, arbol.DocumentElement, nodosSeleccionados)
  26.             Else
  27.                 AnadirNodosAArbol(nodoRaiz, arbol.DocumentElement)
  28.             End If
  29.  
  30.             trvXML.ExpandAll()
  31.  
  32.         Catch ex As Exception
  33.             MsgBox("Se ha producido el siguiente error:" & vbCrLf & vbCrLf & " - " & ex.Message)
  34.         End Try
  35.  
  36.     End Sub
  37.  
  38.     Private Sub AnadirNodosAArbol(ByVal arbol As TreeNode, ByVal nodo As Xml.XmlNode, Optional ByVal nodosSeleccionados As Xml.XmlNodeList = Nothing)
  39.         Dim hijo As Xml.XmlNode
  40.         Dim atr As Xml.XmlAttribute
  41.         Dim nodoArbol As TreeNode
  42.  
  43.         For Each hijo In nodo.ChildNodes
  44.             If hijo.NodeType <> Xml.XmlNodeType.Text And hijo.NodeType <> Xml.XmlNodeType.Comment Then
  45.                 nodoArbol = New TreeNode(hijo.Name)
  46.                 If Not nodosSeleccionados Is Nothing Then
  47.                     If estaSeleccionado(hijo, nodosSeleccionados) Then
  48.                         nodoArbol.ForeColor = Color.Blue
  49.                         nodoArbol.NodeFont = fuenteNegritaArbol
  50.                     End If
  51.                 End If
  52.                 arbol.Nodes.Add(nodoArbol)
  53.                 If textoDelNodo(hijo) <> "" Then
  54.                     nodoArbol.Text &= "=" & textoDelNodo(hijo)
  55.                 End If
  56.                 For Each atr In hijo.Attributes
  57.                     nodoArbol.Text &= "   " & atr.Name & "=" & atr.Value
  58.                 Next
  59.  
  60.                 anadirNodosAArbol(nodoArbol, hijo, nodosSeleccionados)
  61.             End If
  62.         Next
  63.     End Sub

COMPLETANDO LA HERRAMIENTA:

Con esto se habrá terminado el núcleo de nuestra aplicación, habiéndola dotado de la funcionalidad básica para la que se ideó, es decir, el mostrar el xml formateado para que resulte más legible, mostrarlo mediante un árbol y permitir seleccionar nodos mediante XPath visualizando aquellos que respondan a la expresión de búsqueda resaltados.

Vayamos ahora a dotarla de ciertos elementos adicionales para completar la aplicación.

En primer lugar le añadiremos la funcionalidad de permitir ajustar las líneas para que todo el texto de una línea se muestre en pantalla, ocupando las líneas que sean necesarias para mostrarse. Esto es tan sencillo como añadir un checkBox, y establecer la propiedad WordWrap de los RichTextBox al valor de la propiedad Checked del checkBox

Le añadiremos también la funcionalidad de cargar y guardar ficheros. Con este fin se crearán dos elementos de menú y se les asociarán teclas de acceso rápido, CTRL+C y CTRL+G respectivamente. El documento que guardaremos será el xml ya formateado, no el original.

Según vayamos cargando ficheros, éstos se irán incluyendo en la lista de recientes hasta un máximo de cinco. De igual forma incluimos en la lista de ficheros recientes aquéllos documentos que guardemos. El código que realiza esta inserción es el siguiente:

VB.NET:
  1. Private Sub InsertarEnRecientes(ByVal nombreFichero As String)
  2.         Dim menu As MenuItem
  3.         Dim i As Integer
  4.         Dim encontrado As Boolean
  5.  
  6.         Try
  7.             i = 0
  8.             While i <= mnuRecientes.MenuItems.Count - 1 And Not encontrado
  9.                 'Si ya estaba lo quitamos
  10.                 If mnuRecientes.MenuItems(i).Text = nombreFichero Then
  11.                     mnuRecientes.MenuItems.RemoveAt(i)
  12.                     encontrado = True
  13.                 End If
  14.                 i = i + 1
  15.             End While
  16.             menu = New MenuItem(nombreFichero, AddressOf FichReciente_Click)
  17.             mnuRecientes.MenuItems.Add(0, menu)
  18.             If mnuRecientes.MenuItems.Count = 6 Then
  19.                 mnuRecientes.MenuItems.RemoveAt(5)
  20.             End If
  21.         Catch ex As Exception
  22.             MsgBox("Se ha producido el siguiente error:" & vbCrLf & vbCrLf & " - " & ex.Message)
  23.         End Try
  24.  
  25.     End Sub

Cuando se cierre el formulario, se guardará la lista de ficheros recientes en un fichero XML, para que dicha listas persista entre ejecuciones de la aplicación.

VB.NET:
  1. Private Sub GuardarRecientes()
  2.         Dim arbol As New Xml.XmlDocument
  3.         Dim nodo As Xml.XmlNode
  4.         Dim menu As MenuItem
  5.  
  6.         Try
  7.             nodo = arbol.CreateElement("Recientes")
  8.             arbol.AppendChild(nodo)
  9.  
  10.             For Each menu In mnuRecientes.MenuItems
  11.                 nodo = arbol.CreateElement("Fichero")
  12.                 nodo.InnerText = menu.Text
  13.                 arbol.DocumentElement.AppendChild(nodo)
  14.             Next
  15.  
  16.             arbol.Save(Application.StartupPath & "\Recientes.xml")
  17.  
  18.         Catch ex As Exception
  19.             MsgBox("Se ha producido el siguiente error:" & vbCrLf & vbCrLf & " - " & ex.Message)
  20.         End Try
  21.     End Sub

 

Primera parte de este artículo:

Creando un visor de XML (Parte I)

Creando un visor de XML (Parte I)

Martes 12 dAmerica/Chicago Septiembre dAmerica/Chicago 2006 a las 23:58

En este artículo se describe el proceso de desarrollo de una pequeña herramienta que permitirá formatear un documento XML haciendo que resulte más legible, mostrarlo mediante un árbol, y seleccionar nodos mediante XPath visualizando aquéllos que respondan a la expresión de búsqueda resaltados. Adicionalmente se le añadirán otras características secundarias como el guardar y cargar ficheros, una lista de archivos recientes, ajuste de línea y expansión y contracción de todos los nodos del árbol. Es una herramienta sencilla pero que puede ser bastante útil para trabajar con XML.

Debido a sus dimensiones, este artículo ha sido dividido en dos partes. Se puede consultar la segunda parte en la siguiente dirección.

El resultado final de la aplicación mostrando sus tres vistas será el siguiente:

 

(Pulsad la imagen para verla a tamaño real)
Visor
Visor XML. Texto sin formatear.

 

(Pulsad la imagen para verla a tamaño real)
Visor
Visor XML. Vista en árbol.

 

(Pulsad la imagen para verla a tamaño real)
Visor
Visor XML. Texto formateado.

 

FORMATEANDO EL DOCUMENTO XML:

El código para formatear el texto se basa en dos funciones. La primera de ellas se llama FormatearTexto y se encargará de inicializar las variables, cargar el texto introducido en el primer RichTextBox en una variable del tipo XmlDocument. Esta primera función llamará a la segunda (IndentarXML), la cual es una función recursiva que se llamará así misma por cada nodo que tenga el arbol XML.

VB.NET:
  1. Private Sub FormatearTexto(ByVal consultar As Boolean)
  2.         Dim arbol As New Xml.XmlDocument
  3.         Dim profundidad As Integer
  4.         Dim cad As String
  5.  
  6.         'Utilizados solo para hacer la consulta
  7.         Dim nodosSeleccionados As Xml.XmlNodeList
  8.         Dim inicioNodosSeleccionados As ArrayList
  9.         Dim finalNodosSeleccionados As ArrayList
  10.         Dim i As Integer
  11.  
  12.         Try
  13.             arbol.LoadXml(rtxtXML.Text)
  14.  
  15.             profundidad = 0
  16.             cad = ""
  17.             rtxtTextoFormateado.Text = ""
  18.  
  19.             If arbol.FirstChild.NodeType = Xml.XmlNodeType.XmlDeclaration Then
  20.                 cad &= arbol.FirstChild.OuterXml & vbCr
  21.             End If
  22.             If consultar Then
  23.                 nodosSeleccionados = arbol.SelectNodes(txtConsulta.Text)
  24.                 inicioNodosSeleccionados = New ArrayList
  25.                 finalNodosSeleccionados = New ArrayList
  26.                 IndentarXML(arbol.DocumentElement, cad, 0, nodosSeleccionados, inicioNodosSeleccionados, finalNodosSeleccionados)
  27.                 rtxtTextoFormateado.Text = cad
  28.                 For i = 0 To inicioNodosSeleccionados.Count - 1
  29.                     rtxtTextoFormateado.Select(CInt(inicioNodosSeleccionados(i)), CInt(finalNodosSeleccionados(i)) - CInt(inicioNodosSeleccionados(i)))
  30.                     rtxtTextoFormateado.SelectionColor = Color.Blue
  31.                     rtxtTextoFormateado.SelectionFont = fuenteNegritaRTXT
  32.                 Next
  33.             Else
  34.                 IndentarXML(arbol.DocumentElement, cad, profundidad)
  35.                 rtxtTextoFormateado.Text = cad
  36.             End If
  37.         Catch ex As Exception
  38.             MsgBox("Se ha producido el siguiente error:" & vbCrLf & vbCrLf & " - " & ex.Message)
  39.         End Try
  40.     End Sub
  41.  
  42.     Private Function IndentarXML(ByVal nodo As Xml.XmlNode, ByRef cad As String, ByVal profundidad As Integer, Optional ByVal nodosSeleccionados As Xml.XmlNodeList = Nothing, Optional ByVal inicioNodosSeleccionados As ArrayList = Nothing, Optional ByVal finalNodosSeleccionados As ArrayList = Nothing) As String
  43.         Dim hijo As Xml.XmlNode
  44.         Dim atr As Xml.XmlAttribute
  45.  
  46.         If nodo.NodeType <> Xml.XmlNodeType.Text And nodo.NodeType <> Xml.XmlNodeType.Comment Then
  47.             'cad &= New String(Chr(9), profundidad)
  48.             cad &= New String(" "c, profundidad * 7)
  49.  
  50.             If Not nodosSeleccionados Is Nothing AndAlso estaSeleccionado(nodo, nodosSeleccionados) Then
  51.                 If cad = "" Then
  52.                     inicioNodosSeleccionados.Add(0)
  53.                 Else
  54.                     inicioNodosSeleccionados.Add(cad.Length - 1)
  55.                 End If
  56.  
  57.             End If
  58.  
  59.             cad &= "<" & nodo.Name
  60.             For Each atr In nodo.Attributes
  61.                 cad &= " " & atr.Name & "=""" & atr.Value & """"
  62.             Next
  63.             cad &= ">"
  64.  
  65.             If Not nodosSeleccionados Is Nothing AndAlso estaSeleccionado(nodo, nodosSeleccionados) Then
  66.                 finalNodosSeleccionados.Add(cad.Length)
  67.             End If
  68.  
  69.             cad &= textoDelNodo(nodo)
  70.  
  71.             If tieneHijos(nodo) Then
  72.                 cad &= vbCr
  73.                 For Each hijo In nodo.ChildNodes
  74.                     IndentarXML(hijo, cad, profundidad + 1, nodosSeleccionados, inicioNodosSeleccionados, finalNodosSeleccionados)
  75.                 Next
  76.                 'cad &= New String(Chr(9), profundidad)
  77.                 cad &= New String(" "c, profundidad * 7)
  78.             End If
  79.             cad &= "</" & nodo.Name & ">" & vbCr
  80.         End If
  81.     End Function

La función "FormatearTexto" recibe un parámetro que indica si se está realizando una consulta o no. Si es así, se obtendrán todos los nodos seleccionados por la consulta y se crearán dos arrayList para almacenar las posiciones iniciales y finales de los nodos seleccionados, para poder posteriormente resaltarlos en el RichTextBox.

La función "IndentarXML" se encarga de transformar el nodo en cadena formateada y de llamarse a si misma recursivamente por cada hijo que tuviera el nodo. El parámetro profundidad se va incrementando en uno en cada nivel del árbol, y sirve para tabular correctamente el texto de cada nodo. Si se esta consultando y el nodo actual pertenece a los nodos seleccionados por la consulta XPath, entonces se marcará su posición inicial y final añadiéndolas a los arrayList.

Continuación
Creando un visor de XML (Parte II)

Incorporado intellisense al editor

Domingo 10 dAmerica/Chicago Septiembre dAmerica/Chicago 2006 a las 23:47

He dotado al editor de código con intellisense. Esta funcionalidad resulta muy útil a la hora de escribir código ya que aumenta considerablemente la productividad del desarrollador. No es demasiado compleja de implementar. Hoy en día la inmensa mayoría de entornos de desarrollo incorporan esta característica.

El Intellisense se activa al presionar la combinación de teclas + J, con lo que se mostrará una lista con todas las palabras, posicionándose el foco en aquella palabra que encaje con lo que hay escrito en el editor o en la primera de ellas si hubiera varias que encajaran. Se podrá seleccionar mediante los cursores la palabra deseada y al pulsar la barra espaciadora o la tecla ENTER se escribirá dicha palabra en el editor, desapareciendo la lista de palabras. Si pulsáramos la tecla ESC una vez se esta mostrando la lista de palabras, esta desaparecería.

Actualmente la lista de palabras únicamente muestra las palabras del lenguaje, pero no muestra variables o constantes que se hayan declarado previamente en el código. Cuando finalice la implantación de los analizadores incluirá las variables y las constantes en la lista.


Intellisense."
Intellisense.


Arkanoid

Viernes 8 dAmerica/Chicago Septiembre dAmerica/Chicago 2006 a las 23:59

El clásico Arkanoid. Está desarrollado con Visual Basic.NET utilizando el framework 1.1. Este sencillo juego lo implementé a finales del 2004, después de finalizar el Tetris y me llevó muy poco tiempo. Consta únicamente de 727 líneas.

La nave puede ser manejada tanto con el teclado como con el ratón. Según destruyes ladrillos se va descubriendo una imagen tapada inicialmente por un telón negro y se van adquiriendo puntos. El jugador comienza con tres vidas que irá perdiendo cuando no consiga alcanzar la pelota con la nave. No consta más que de un nivel, aunque sería muy sencillo agregarle nuevos niveles.

Usa un único sonido que se reproduce al impactar la pelota contra los ladrillos y solo consta de tres imágenes: la pelota, la nave y el ladrillo (además de la imagen que se descubre a la derecha). Los gráficos se dibujan utilizando GDI+ con la técnica del doble buffer para evitar los molestos parpadeos. Soy conciente de las deficiencias de los gráficos, pero mis habilidades con el paint no dan para más.


Tetris.
(Pulsad la imagen para verla a tamaño real)
Arkanoid.


Estado del proyecto a 07/09/2006

Jueves 7 dAmerica/Chicago Septiembre dAmerica/Chicago 2006 a las 23:57

Aparte de lo comentado en un post anterior hace unos días este es el estado del motor de aventuras gráficas a día de hoy.

He terminado el analizador sintáctico, aunque probablemente tenga que hacerle alguna modificación posteriormente para adaptarlo al analizador semántico. Todavía no he diseñado el analizador semántico, por lo que los datos de entrada que recibirá del sintáctico aun no están definidos por lo que tendré que hacer modificaciones al sintáctico para adaptarlo a lo esperado por el semántico.

A la hora de desarrollarlo he tenido algún contratiempo, ya que después de definir el lenguaje, expresarlo en notación BNF, calcular los símbolos directores e implementarlo, me he dado cuenta de que había dos producciones en las que a partir de un mismo no terminal compartían el mismo símbolo director, por lo que el analizador no era capaz de elegir la producción correcta de las dos posibles.

Finalmente me decidí por hacer una pequeña modificación al lenguaje para evitar dicho problema. Inicialmente el salto de línea era el separador de sentencias como en el lenguaje Visual Basic. Ahora es el punto, al igual que en las frases del lenguaje natural.

Cuando tenga una versión mas o menos definitiva del analizador sintáctico escribiré un par de posts sobre el proceso de desarrollo, incluyendo algunas capturas y fragmentos de código.