En este ejemplo se muestra una forma de implementar los AstNodes en Irony:
El Código Fuente
Esta imagen muestra la funcionalidad que tiene el programa.
Como se observa Realiza la Operacion Aritmetica 4+5*8-20 la diferencia es que en lugar de recorrer el arbol que genera por default irony se utiliza ast nodes de manera que la forma de recorrerlo se hace mas natural con los astnodes
El arbol generado por astnodes para la entrada de la imagen es.
El arbol generado por default por irony para la entrada es
Al observar los 2 arboles se puede ver que con la ayuda de astnodes podemos practicamente eliminar los nodos que no nos sirven y poder colocarlos a nuestra manera para una implementacion mas sencilla y mas eficiente.
En el archivo se hace el comentario de que la instrucción:
this.LanguageFlags = LanguageFlags.CreateAst;
es muy importante ya que es la directiva para crear el Árbol.
Cabe mencionar que se tiene que añadir como referencia los dos dll mencionados en publicaciones anteriores:
1)Irony.dll
2)Irony.Interpreter.dll
Si la descarga no se realiza correctamente Este es el codigo principal de la generacion del arbol ast:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Irony.Parsing;
using Irony.Ast;
using Irony.Interpreter.Ast;
using System.Collections;
/**
* PROYECTO QUE REALIZA SUMAS RESTAS MULTIPLICACIONES Y DIVICIONES DE NUMEROS IMPLEMENTANDO IRONY
* */
namespace WindowsFormsApplication1
{
/**
* CLASE ARBOL
* HEREDA DE ASTNODE PARA QUE SE PUEDA IMPLEMENTAR EN LOS NO TERMINALES
* EL METODO A SOBREESCRIBIR ES INIT QUE SE EJECUTARA AL REDUCIR POR EL NOTERMINAL QUE IMPLEMENTE ESTA CLASE
* LOS PARAMETROS SERA EL CONTEXTO Y EL PARSETREENODE QUE SE REDUJO
* */
public class Arbol : AstNode
{
public Object Name;
public List<Arbol> hijos;
public override void Init(Irony.Ast.AstContext context, Irony.Parsing.ParseTreeNode treeNode)
{
hijos = new List<Arbol>();//inicializamos la lista
base.Init(context, treeNode);
switch ((String)treeNode.Term.Name)
{ // 0 1 2
case "E":// E + E | E - E | E * E | num
if (treeNode.ChildNodes.Count > 1)
{
Name = treeNode.ChildNodes[1].FindTokenAndGetText(); //SIGNO
hijos.Add((Arbol)treeNode.ChildNodes[0].AstNode); // PRIMER VALOR
hijos.Add((Arbol)treeNode.ChildNodes[2].AstNode); // SEGUNDO VALOR
} else
{
Name = treeNode.ChildNodes[0].FindTokenAndGetText(); //OBTENEMOS EL NUMERO
}
break;
case "number":
Name = treeNode.Token.Text;
break;
default:
break;
}
}
}
class analizador : Grammar
{
//METODO QUE RECORRERA EL ARBOL AST
public Double Valor(Arbol arbol)
{
Double entero1;
Double entero2;
switch ((String)arbol.Name)
{
case "+":
entero1 = Valor(arbol.hijos[0]);
entero2 = Valor(arbol.hijos[1]);
return entero1 + entero2;
case "-":
entero1 = Valor(arbol.hijos[0]);
entero2 = Valor(arbol.hijos[1]);
return entero1 - entero2;
case "*":
entero1 = Valor(arbol.hijos[0]);
entero2 = Valor(arbol.hijos[1]);
return entero1 * entero2;
case "/":
entero1 = Valor(arbol.hijos[0]);
entero2 = Valor(arbol.hijos[1]);
return entero1 / entero2;
default:
return Convert.ToDouble(arbol.Name);
}
}
public analizador() {
var number = new RegexBasedTerminal("number", "[0-9]+");
var singleLineComment = new CommentTerminal("SingleLineComment", "//", "\r", "\n", "\u2085", "\u2028", "\u2029");
var delimitedComment = new CommentTerminal("DelimitedComment", "/*", "*/");
var p = new StringLiteral("p", "\"");
p.AstConfig.NodeType = typeof(Arbol);
number.AstConfig.NodeType = typeof(Arbol);
NonTerminal E = new NonTerminal("E",typeof(Arbol));
E.Rule = E + ToTerm("+") + E
| E + ToTerm("-") + E
| E + ToTerm("*") + E
| E + ToTerm("/") + E
| number;
RegisterOperators(1, "+", "-");//ESTABLESEMOS PRESEDENCIA
RegisterOperators(2, "*", "/");
this.Root = E;
NonGrammarTerminals.Add(singleLineComment); // QUITAMOS LOS COMENTARIOS DE LA GRAMATICA
NonGrammarTerminals.Add(delimitedComment);
LanguageFlags = LanguageFlags.CreateAst; //IMPORTANTE PARA CREAR EL ARBOL SIN ESTO NO LO CREARA
}
public Double Obtener_Resultado(string sourceCode)
{
LanguageData language = new LanguageData(this);
Parser parser = new Parser(language);
ParseTree parseTree = parser.Parse(sourceCode);
ParseTreeNode root = parseTree.Root;
Arbol a = (Arbol)root.AstNode;
return Valor(a); //OBTENEMOS EL VALRO DE LA ENTRADA
}
}
}
El código fuente ya no está disponible
ResponderEliminar