domingo, 7 de septiembre de 2014

Estableciendo orden y precedencia de operadores en Irony .NET

Como sabemos, en los lenguajes de programación es necesario que se establezca el orden en el que se opera y se analiza el código.
El ejemplo más común, y tal vez el más acertado para aprender sobre el tema es al utilizar operaciones aritméticas, como en la siguiente gramática (escrita para Irony):

/* Terminales */
         RegexBasedTerminal mas   = new RegexBasedTerminal("suma", "[+]");
         RegexBasedTerminal menos = new RegexBasedTerminal("resta", "[-]");
         RegexBasedTerminal por   = new RegexBasedTerminal("multiplicacion","[*]");
         RegexBasedTerminal div   = new RegexBasedTerminal("division", "[/]");
         RegexBasedTerminal mod   = new RegexBasedTerminal("mod", "[%]");
         RegexBasedTerminal neg   = new RegexBasedTerminal("mod", "[~]");

/* No terminales */
VALOR.Rule
                = VALOR + por + VALOR
                | VALOR + div + VALOR
                | VALOR + mod + VALOR
                | VALOR + exp + VALOR
                | VALOR + mas + VALOR
                | VALOR + menos + VALOR
                | id
                | entero
                | neg + VALOR ;


El problema con esta gramática es que el árbol se puede generar de varias formas para la misma entrada (la gramática tiene ambigüedad) por lo que para la entrada:
1 + 2 * 3 - 4 % ~5

Se puede generar el árbol:


El cual ejecutando realizaría como resultado:
((((1+2) * 3) - 4) % ~5) = 0

Para lo cual escribimos la precedencia de operadores:

/* Precedencia */
            RegisterOperators(1, smas, smenos);
            RegisterOperators(2, spor, sdiv, mod);

            RegisterOperators(3, Associativity.Left, neg);

Lo cual nos generaría un árbol que si da el resultado esperado:

((1 +( 2 * 3)) - (4 % (~5)))

Como es de notar se puede establecer que un signo tenga asociatividad por la izquierda o por la derecha, de la siguiente forma:

            RegisterOperators(3, Associativity.Left, neg);
          RegisterOperators(3, Associativity.Right, neg);

Y de esta forma establecemos prioridades y precedencia en Irony .net...

No hay comentarios:

Publicar un comentario