Al contrario que la mayoría de analizadores yacc/lex Irony
no emplea generación de código para parser o scanner basado en un meta lenguaje
específico.
Irony utiliza la gramática codificada como una clase c# para
controlar el proceso de parsing
Aquí mostramos un ejemplo:
using
System;
using
System.Collections.Generic;
using System.Text;
using
Irony.Parsing;
using
Irony.Ast;
namespace
Irony.Samples {
// Esta gramática describe programas
que reconocen expresiones
//simples y asignaciones
// por Ej:
// x = 3
// y = -x + 5
[Language("ExpressionEvaluator",
"1.0", "Multi-line expression evaluator")]
public class ExpressionEvaluatorGrammar :
Irony.Parsing.Grammar {
public ExpressionEvaluatorGrammar() {
// 1. Terminales
var number = new
NumberLiteral("number");
number.DefaultIntTypes = new TypeCode[] {
TypeCode.Int32,
TypeCode.Int64,
NumberLiteral.TypeCodeBigInt };
var identifier = new
IdentifierTerminal("identifier");
var comment = new
CommentTerminal("comment", "#", "\n",
"\r");
//los comentarios deben agregarse
a la lista NonGrammarTerminals;
//no se utiliza
directamente en la gramática,
// asi que
debemos agregarlo para que el Scanner sepa que es
//un terminal
válido.
base.NonGrammarTerminals.Add(comment);
// 2.
No-terminales
var Expr = new
NonTerminal("Expr");
var Term = new
NonTerminal("Term");
var BinExpr = new
NonTerminal("BinExpr", typeof(BinExprNode));
var ParExpr = new
NonTerminal("ParExpr");
var UnExpr = new NonTerminal("UnExpr",
typeof(UnExprNode));
var UnOp = new
NonTerminal("UnOp");
var BinOp = new
NonTerminal("BinOp", "operator");
var PostFixExpr = new
NonTerminal("PostFixExpr", typeof(UnExprNode));
var PostFixOp = new
NonTerminal("PostFixOp");
var AssignmentStmt = new
NonTerminal("AssignmentStmt", typeof(AssigmentNode));
var AssignmentOp = new
NonTerminal("AssignmentOp", "assignment operator");
var Statement = new
NonTerminal("Statement");
var ProgramLine = new NonTerminal("ProgramLine");
var Program = new
NonTerminal("Program", typeof(StatementListNode));
// 3. Reglas en formato BNF
Expr.Rule = Term | UnExpr | BinExpr |
PostFixExpr;
Term.Rule = number | ParExpr |
identifier;
ParExpr.Rule = "(" + Expr +
")";
UnExpr.Rule = UnOp + Term;
UnOp.Rule = ToTerm("+") |
"-" | "++" | "--";
BinExpr.Rule = Expr + BinOp + Expr;
BinOp.Rule = ToTerm("+") |
"-" | "*" | "/" | "**";
PostFixExpr.Rule = Term + PostFixOp;
PostFixOp.Rule = ToTerm("++") |
"--";
AssignmentStmt.Rule = identifier +
AssignmentOp + Expr;
AssignmentOp.Rule = ToTerm("=")
| "+=" | "-=" | "*=" | "/=";
Statement.Rule = AssignmentStmt | Expr |
Empty;
ProgramLine.Rule = Statement + NewLine;
Program.Rule = MakeStarRule(Program,
ProgramLine);
this.Root = Program; // Se coloca la Raiz
// 4.
Precedencia de Operadores
RegisterOperators(1, "+",
"-");
RegisterOperators(2, "*",
"/");
RegisterOperators(3, Associativity.Right,
"**");
// 5. Terminos de puntuación
RegisterPunctuation("(", ")");
RegisterBracePair("(", ")");
MarkTransient(Term, Expr, Statement,
BinOp, UnOp, PostFixOp,
AssignmentOp, ProgramLine, ParExpr);
//añade
automáticamente un salto de línea antes del EOF para
//que las reglas
funcionen correctamente cuando no haya salto
//de linea al final del
archivo
this.LanguageFlags = LanguageFlags.CreateAst
| LanguageFlags.NewLineBeforeEOF |
LanguageFlags.CanRunSample;
}
}
}//namespace
No hay comentarios:
Publicar un comentario