internal BnfTerms(TerminalFactoryS TerminalFactoryS) { this.ADD_OP = TerminalFactoryS.CreateKeyTerm("+", D.BinaryOperator.Add); this.SUB_OP = TerminalFactoryS.CreateKeyTerm("-", D.BinaryOperator.Sub); this.MUL_OP = TerminalFactoryS.CreateKeyTerm("*", D.BinaryOperator.Mul); this.DIV_OP = TerminalFactoryS.CreateKeyTerm("/", D.BinaryOperator.Div); this.POW_OP = TerminalFactoryS.CreateKeyTerm("^", D.BinaryOperator.Pow); this.MOD_OP = TerminalFactoryS.CreateKeyTerm("%", D.BinaryOperator.Mod); this.POS_OP = TerminalFactoryS.CreateKeyTerm("+", D.UnaryOperator.Pos); this.NEG_OP = TerminalFactoryS.CreateKeyTerm("-", D.UnaryOperator.Neg); this.EQ_OP = TerminalFactoryS.CreateKeyTerm("==", D.BinaryOperator.Eq); this.NEQ_OP = TerminalFactoryS.CreateKeyTerm("<>", D.BinaryOperator.Neq); this.LT_OP = TerminalFactoryS.CreateKeyTerm("<", D.BinaryOperator.Lt); this.LTE_OP = TerminalFactoryS.CreateKeyTerm("<=", D.BinaryOperator.Lte); this.GT_OP = TerminalFactoryS.CreateKeyTerm(">", D.BinaryOperator.Gt); this.GTE_OP = TerminalFactoryS.CreateKeyTerm(">=", D.BinaryOperator.Gte); this.AND_OP = TerminalFactoryS.CreateKeyTerm("&&", D.BinaryOperator.And); this.OR_OP = TerminalFactoryS.CreateKeyTerm("||", D.BinaryOperator.Or); this.NOT_OP = TerminalFactoryS.CreateKeyTerm("!", D.UnaryOperator.Not); this.QUESTION_MARK_COLON = TerminalFactoryS.CreateKeyTerm("?:"); this.BOOL_CONSTANT = new BnfiTermConstant <bool>() { { "true", true }, { "false", false } }; this.LEFT_PAREN = TerminalFactoryS.CreateKeyTerm("("); this.RIGHT_PAREN = TerminalFactoryS.CreateKeyTerm(")"); }
public GrammarFunction() : base(new Domain()) { B = new BnfTerms(new TerminalFactoryS(this)); this.Root = B.Expression; B.Expression.SetRuleOr( B.BinaryExpression, B.UnaryExpression, B.ConditionalTernaryExpression, B.NumberLiteral, B.BoolLiteral ); B.BinaryExpression.Rule = B.BinaryOperator.BindTo(B.BinaryExpression, t => t.Op) + B.LEFT_PAREN + B.Expression.BindTo(B.BinaryExpression, t => t.Term1) + B.COMMA + B.Expression.BindTo(B.BinaryExpression, t => t.Term2) + B.RIGHT_PAREN ; B.UnaryExpression.Rule = B.UnaryOperator.BindTo(B.UnaryExpression, t => t.Op) + B.LEFT_PAREN + B.Expression.BindTo(B.UnaryExpression, t => t.Term) + B.RIGHT_PAREN ; B.ConditionalTernaryExpression.Rule = B.CONDITIONAL_TERNARY + B.LEFT_PAREN + B.Expression.BindTo(B.ConditionalTernaryExpression, t => t.Cond) + B.COMMA + B.Expression.BindTo(B.ConditionalTernaryExpression, t => t.Term1) + B.COMMA + B.Expression.BindTo(B.ConditionalTernaryExpression, t => t.Term2) + B.RIGHT_PAREN ; var numberLiteralInfo = new NumberLiteralInfo() .AddPrefix("#b", NumberLiteralBase.Binary) .AddPrefix("#o", NumberLiteralBase.Octal) .AddPrefix("#x", NumberLiteralBase.Hexadecimal); B.NumberLiteral.Rule = TerminalFactoryS.CreateNumberLiteral <D.NumberLiteral>(numberLiteralInfo); B.BoolLiteral.Rule = B.BOOL_CONSTANT.BindTo(B.BoolLiteral, t => t.Value); B.BinaryOperator.Rule = B.ADD_OP | B.SUB_OP | B.MUL_OP | B.DIV_OP | B.POW_OP | B.MOD_OP | B.EQ_OP | B.NEQ_OP | B.LT_OP | B.LTE_OP | B.GT_OP | B.GTE_OP | B.AND_OP | B.OR_OP; B.UnaryOperator.Rule = B.POS_OP | B.NEG_OP | B.NOT_OP; RegisterBracePair(B.LEFT_PAREN, B.RIGHT_PAREN); }
internal BnfTerms(TerminalFactoryS TerminalFactoryS) { this.OBJECT_BEGIN = TerminalFactoryS.CreateKeyTerm("{"); this.OBJECT_END = TerminalFactoryS.CreateKeyTerm("}"); this.ARRAY_BEGIN = TerminalFactoryS.CreateKeyTerm("["); this.ARRAY_END = TerminalFactoryS.CreateKeyTerm("]"); this.COMMA = TerminalFactoryS.CreateKeyTerm(","); this.COLON = TerminalFactoryS.CreateKeyTerm(":"); this.NUMBER = TerminalFactoryS.CreateNumberLiteral(); this.STRING = TerminalFactoryS.CreateStringLiteral(name: "stringliteral", startEndSymbol: "\""); this.BOOLEAN = new BnfiTermConstant <bool>() { { "true", true }, { "false", false } }; this.NULL = new BnfiTermConstantTL() { { "null", (object)null } }; }
internal BnfTerms(TerminalFactoryS TerminalFactoryS) { this.ADD_OP = TerminalFactoryS.CreateKeyTerm("Add", D.BinaryOperator.Add); this.SUB_OP = TerminalFactoryS.CreateKeyTerm("Sub", D.BinaryOperator.Sub); this.MUL_OP = TerminalFactoryS.CreateKeyTerm("Mul", D.BinaryOperator.Mul); this.DIV_OP = TerminalFactoryS.CreateKeyTerm("Div", D.BinaryOperator.Div); this.POW_OP = TerminalFactoryS.CreateKeyTerm("Pow", D.BinaryOperator.Pow); this.MOD_OP = TerminalFactoryS.CreateKeyTerm("Mod", D.BinaryOperator.Mod); this.POS_OP = TerminalFactoryS.CreateKeyTerm("Pos", D.UnaryOperator.Pos); this.NEG_OP = TerminalFactoryS.CreateKeyTerm("Neg", D.UnaryOperator.Neg); this.EQ_OP = TerminalFactoryS.CreateKeyTerm("Eq", D.BinaryOperator.Eq); this.NEQ_OP = TerminalFactoryS.CreateKeyTerm("Neq", D.BinaryOperator.Neq); this.LT_OP = TerminalFactoryS.CreateKeyTerm("Lt", D.BinaryOperator.Lt); this.LTE_OP = TerminalFactoryS.CreateKeyTerm("Lte", D.BinaryOperator.Lte); this.GT_OP = TerminalFactoryS.CreateKeyTerm("Gt", D.BinaryOperator.Gt); this.GTE_OP = TerminalFactoryS.CreateKeyTerm("Gte", D.BinaryOperator.Gte); this.AND_OP = TerminalFactoryS.CreateKeyTerm("And", D.BinaryOperator.And); this.OR_OP = TerminalFactoryS.CreateKeyTerm("Or", D.BinaryOperator.Or); this.NOT_OP = TerminalFactoryS.CreateKeyTerm("Not", D.UnaryOperator.Not); this.CONDITIONAL_TERNARY = TerminalFactoryS.CreateKeyTerm("Cond"); this.COMMA = TerminalFactoryS.CreateKeyTerm(","); this.BOOL_CONSTANT = new BnfiTermConstant <bool>() { { "true", true }, { "false", false } }; this.LEFT_PAREN = TerminalFactoryS.CreateKeyTerm("("); this.RIGHT_PAREN = TerminalFactoryS.CreateKeyTerm(")"); }
internal BnfTerms(TerminalFactoryS TerminalFactoryS, CultureInfo cultureInfo) { if (cultureInfo.Name == "hu") { this.PROGRAM = TerminalFactoryS.CreateKeyTerm("program"); this.NAMESPACE = TerminalFactoryS.CreateKeyTerm("névtér"); this.BEGIN = TerminalFactoryS.CreateKeyTerm("eleje"); this.END = TerminalFactoryS.CreateKeyTerm("vége"); this.FUNCTION = TerminalFactoryS.CreateKeyTerm("függvény"); this.WHILE = TerminalFactoryS.CreateKeyTerm("amíg"); this.FOR = TerminalFactoryS.CreateKeyTerm("ciklus"); this.IF = TerminalFactoryS.CreateKeyTerm("ha"); this.THEN = TerminalFactoryS.CreateKeyTerm("akkor"); this.ELSE = TerminalFactoryS.CreateKeyTerm("egyébként"); this.DO = TerminalFactoryS.CreateKeyTerm("csináld"); this.RETURN = TerminalFactoryS.CreateKeyTerm("visszatér"); this.WRITE = TerminalFactoryS.CreateKeyTerm("Kiír"); this.WRITELN = TerminalFactoryS.CreateKeyTerm("KiírSor"); this.VAR = TerminalFactoryS.CreateKeyTerm("változó"); this.ASYNC = TerminalFactoryS.CreateKeyTerm("aszink", true); this.AND_OP = TerminalFactoryS.CreateKeyTerm("és", DE.BinaryOperator.And); this.OR_OP = TerminalFactoryS.CreateKeyTerm("vagy", DE.BinaryOperator.Or); this.NOT_OP = TerminalFactoryS.CreateKeyTerm("nem", DE.UnaryOperator.Not); this.INTEGER_TYPE = TerminalFactoryS.CreateKeyTerm("egész", D.Type.Integer); this.REAL_TYPE = TerminalFactoryS.CreateKeyTerm("valós", D.Type.Real); this.STRING_TYPE = TerminalFactoryS.CreateKeyTerm("karakterlánc", D.Type.String); this.CHAR_TYPE = TerminalFactoryS.CreateKeyTerm("karakter", D.Type.Char); this.BOOL_TYPE = TerminalFactoryS.CreateKeyTerm("logikai", D.Type.Bool); this.COLOR_TYPE = TerminalFactoryS.CreateKeyTerm("szín", D.Type.Color); this.DATE_TYPE = TerminalFactoryS.CreateKeyTerm("dátum", D.Type.Date); this.BOOL_CONSTANT = new BnfiTermConstant <bool>() { { "igaz", true }, { "hamis", false } }; this.COLOR_CONSTANT = new BnfiTermConstant <D.Color>() { { "szín_fekete", D.Color.Black }, { "szín_kék", D.Color.Blue }, { "szín_barna", D.Color.Brown }, { "szín_szürke", D.Color.Gray }, { "szín_zöld", D.Color.Green }, { "szín_narancs", D.Color.Orange }, { "szín_piros", D.Color.Red }, { "szín_fehér", D.Color.White }, { "szín_sárga", D.Color.Yellow } }; } else if (cultureInfo.Name == "de") { this.PROGRAM = TerminalFactoryS.CreateKeyTerm("Programm"); this.NAMESPACE = TerminalFactoryS.CreateKeyTerm("NameRaum"); this.BEGIN = TerminalFactoryS.CreateKeyTerm("Beginn"); this.END = TerminalFactoryS.CreateKeyTerm("Ende"); this.FUNCTION = TerminalFactoryS.CreateKeyTerm("Funktion"); this.WHILE = TerminalFactoryS.CreateKeyTerm("während"); this.FOR = TerminalFactoryS.CreateKeyTerm("Zyklus"); this.IF = TerminalFactoryS.CreateKeyTerm("wenn"); this.THEN = TerminalFactoryS.CreateKeyTerm("dann"); this.ELSE = TerminalFactoryS.CreateKeyTerm("sonst"); this.DO = TerminalFactoryS.CreateKeyTerm("tun"); this.RETURN = TerminalFactoryS.CreateKeyTerm("zurückholen"); this.WRITE = TerminalFactoryS.CreateKeyTerm("Schreiben"); this.WRITELN = TerminalFactoryS.CreateKeyTerm("SchreibenLeine"); this.VAR = TerminalFactoryS.CreateKeyTerm("Variable"); this.ASYNC = TerminalFactoryS.CreateKeyTerm("async", true); this.AND_OP = TerminalFactoryS.CreateKeyTerm("und", DE.BinaryOperator.And); this.OR_OP = TerminalFactoryS.CreateKeyTerm("oder", DE.BinaryOperator.Or); this.NOT_OP = TerminalFactoryS.CreateKeyTerm("nicht", DE.UnaryOperator.Not); this.INTEGER_TYPE = TerminalFactoryS.CreateKeyTerm("Ganzzahl", D.Type.Integer); this.REAL_TYPE = TerminalFactoryS.CreateKeyTerm("ReeleZahl", D.Type.Real); this.STRING_TYPE = TerminalFactoryS.CreateKeyTerm("Schnur", D.Type.String); this.CHAR_TYPE = TerminalFactoryS.CreateKeyTerm("Charakter", D.Type.Char); this.BOOL_TYPE = TerminalFactoryS.CreateKeyTerm("Boolsche", D.Type.Bool); this.COLOR_TYPE = TerminalFactoryS.CreateKeyTerm("Farbe", D.Type.Color); this.DATE_TYPE = TerminalFactoryS.CreateKeyTerm("Datum", D.Type.Date); this.BOOL_CONSTANT = new BnfiTermConstant <bool>() { { "richtig", true }, { "falsch", false } }; this.COLOR_CONSTANT = new BnfiTermConstant <D.Color>() { { "Farbe_schwarz", D.Color.Black }, { "Farbe_blau", D.Color.Blue }, { "Farbe_braun", D.Color.Brown }, { "Farbe_grau", D.Color.Gray }, { "Farbe_grün", D.Color.Green }, { "Farbe_orange", D.Color.Orange }, { "Farbe_rot", D.Color.Red }, { "Farbe_weiss", D.Color.White }, { "Farbe_gelb", D.Color.Yellow } }; } else { this.PROGRAM = TerminalFactoryS.CreateKeyTerm("program"); this.NAMESPACE = TerminalFactoryS.CreateKeyTerm("namespace"); this.BEGIN = TerminalFactoryS.CreateKeyTerm("begin"); this.END = TerminalFactoryS.CreateKeyTerm("end"); this.FUNCTION = TerminalFactoryS.CreateKeyTerm("function"); this.WHILE = TerminalFactoryS.CreateKeyTerm("while"); this.FOR = TerminalFactoryS.CreateKeyTerm("for"); this.IF = TerminalFactoryS.CreateKeyTerm("if"); this.THEN = TerminalFactoryS.CreateKeyTerm("then"); this.ELSE = TerminalFactoryS.CreateKeyTerm("else"); this.DO = TerminalFactoryS.CreateKeyTerm("do"); this.RETURN = TerminalFactoryS.CreateKeyTerm("return"); this.WRITE = TerminalFactoryS.CreateKeyTerm("Write"); this.WRITELN = TerminalFactoryS.CreateKeyTerm("WriteLn"); this.VAR = TerminalFactoryS.CreateKeyTerm("var"); this.ASYNC = TerminalFactoryS.CreateKeyTerm("async", true); this.AND_OP = TerminalFactoryS.CreateKeyTerm("and", DE.BinaryOperator.And); this.OR_OP = TerminalFactoryS.CreateKeyTerm("or", DE.BinaryOperator.Or); this.NOT_OP = TerminalFactoryS.CreateKeyTerm("not", DE.UnaryOperator.Not); this.INTEGER_TYPE = TerminalFactoryS.CreateKeyTerm("integer", D.Type.Integer); this.REAL_TYPE = TerminalFactoryS.CreateKeyTerm("real", D.Type.Real); this.STRING_TYPE = TerminalFactoryS.CreateKeyTerm("string", D.Type.String); this.CHAR_TYPE = TerminalFactoryS.CreateKeyTerm("char", D.Type.Char); this.BOOL_TYPE = TerminalFactoryS.CreateKeyTerm("boolean", D.Type.Bool); this.COLOR_TYPE = TerminalFactoryS.CreateKeyTerm("color", D.Type.Color); this.DATE_TYPE = TerminalFactoryS.CreateKeyTerm("date", D.Type.Date); this.BOOL_CONSTANT = new BnfiTermConstant <bool>() { { "True", true }, { "False", false } }; this.COLOR_CONSTANT = new BnfiTermConstant <D.Color>() { { "Color_Black", D.Color.Black }, { "Color_Blue", D.Color.Blue }, { "Color_Brown", D.Color.Brown }, { "Color_Gray", D.Color.Gray }, { "Color_Green", D.Color.Green }, { "Color_Orange", D.Color.Orange }, { "Color_Red", D.Color.Red }, { "Color_White", D.Color.White }, { "Color_Yellow", D.Color.Yellow } }; } this.DOT = TerminalFactoryS.CreateKeyTerm("."); this.LET = TerminalFactoryS.CreateKeyTerm(":="); this.SEMICOLON = TerminalFactoryS.CreateKeyTerm(";"); this.COLON = TerminalFactoryS.CreateKeyTerm(":"); this.COMMA = TerminalFactoryS.CreateKeyTerm(","); this.LEFT_PAREN = TerminalFactoryS.CreateKeyTerm("("); this.RIGHT_PAREN = TerminalFactoryS.CreateKeyTerm(")"); this.QUESTION_MARK = TerminalFactoryS.CreateKeyTerm("?"); this.ADD_OP = TerminalFactoryS.CreateKeyTerm("+", DE.BinaryOperator.Add); this.SUB_OP = TerminalFactoryS.CreateKeyTerm("-", DE.BinaryOperator.Sub); this.MUL_OP = TerminalFactoryS.CreateKeyTerm("*", DE.BinaryOperator.Mul); this.DIV_OP = TerminalFactoryS.CreateKeyTerm("/", DE.BinaryOperator.Div); this.POW_OP = TerminalFactoryS.CreateKeyTerm("^", DE.BinaryOperator.Pow); this.MOD_OP = TerminalFactoryS.CreateKeyTerm("%", DE.BinaryOperator.Mod); this.POS_OP = TerminalFactoryS.CreateKeyTerm("+", DE.UnaryOperator.Pos); this.NEG_OP = TerminalFactoryS.CreateKeyTerm("-", DE.UnaryOperator.Neg); this.EQ_OP = TerminalFactoryS.CreateKeyTerm("=", DE.BinaryOperator.Eq); this.NEQ_OP = TerminalFactoryS.CreateKeyTerm("<>", DE.BinaryOperator.Neq); this.LT_OP = TerminalFactoryS.CreateKeyTerm("<", DE.BinaryOperator.Lt); this.LTE_OP = TerminalFactoryS.CreateKeyTerm("<=", DE.BinaryOperator.Lte); this.GT_OP = TerminalFactoryS.CreateKeyTerm(">", DE.BinaryOperator.Gt); this.GTE_OP = TerminalFactoryS.CreateKeyTerm(">=", DE.BinaryOperator.Gte); // NOTE: to parse keyterms with international characters properly we need to allow international characters in identifiers as well: // CreateCSharpIdentifier creates an identifier terminal that allows internation characters // this.IDENTIFIER = TerminalFactoryS.CreateIdentifier(); this.IDENTIFIER = TerminalFactory.CreateCSharpIdentifier("identifier").IntroIdentifier(); }
public GrammarP(CultureInfo cultureInfo) : base(new Domain()) { B = new BnfTerms(new TerminalFactoryS(this), cultureInfo); this.DefaultCulture = cultureInfo; this.Root = B.Program; B.Program.Rule = B.PROGRAM + B.Name.BindTo(B.Program, t => t.Name) + (B.NAMESPACE + B.NamespaceName).QRef().BindTo(B.Program, t => t.Namespace) + B.Function.StarList().BindTo(B.Program, t => t.Functions) + B.BEGIN + B.Statement.PlusList().BindTo(B.Program, t => t.Body) + B.END + B.DOT ; B.Function.Rule = B.FUNCTION + B.ASYNC.QVal(false).BindTo(B.Function, t => t.IsAsync) + B.Name.BindTo(B.Function, t => t.Name) + B.LEFT_PAREN + B.Parameter.StarList(B.COMMA).BindTo(B.Function, t => t.Parameters) + B.RIGHT_PAREN + (B.COLON + B.Type).QVal().BindTo(B.Function, t => t.ReturnType) + B.BEGIN + B.Statement.PlusList().BindTo(B.Function, t => t.Body) + B.END ; B.Parameter.Rule = B.VAR + B.Name.BindTo(B.Parameter, t => t.Name) + B.COLON + B.Type.BindTo(B.Parameter, t => t.Type) ; B.Statement.SetRuleOr( B.LocalVariable + B.SEMICOLON, B.Assignment + B.SEMICOLON, B.While, B.For, B.If, #if SEPARATE_IFELSE B.IfElse, #endif B.FunctionCall + B.SEMICOLON, B.Write + B.SEMICOLON, B.WriteLn + B.SEMICOLON, B.Return + B.SEMICOLON, B.StatementList ); B.Return.Rule = B.RETURN + B.Expression.BindTo(B.Return, t => t.Value) ; B.LocalVariable.Rule = B.VAR + B.Name.BindTo(B.LocalVariable, t => t.Name) + B.COLON + B.Type.BindTo(B.LocalVariable, t => t.Type) + (B.LET + B.Expression).QRef().BindTo(B.LocalVariable, t => t.InitValue) ; B.Assignment.Rule = B.VariableReference.BindTo(B.Assignment, t => t.LValue) + B.LET + B.Expression.BindTo(B.Assignment, t => t.RValue) ; B.VariableReference.Rule = B.NameRef .ConvertValue(_nameRef => ReferenceFactory.Get <D.IVariable>(_nameRef), _variableReference => _variableReference.NameRef) .BindTo(B.VariableReference, t => t.Target) ; B.FunctionReference.Rule = B.NameRef.ConvertValue(_nameRef => ReferenceFactory.Get <D.Function>(_nameRef), _functionReference => _functionReference.NameRef) ; B.StatementList.Rule = B.BEGIN + B.Statement.PlusList().BindTo(B.StatementList, t => t.Body) + B.END ; B.While.Rule = B.WHILE + B.LEFT_PAREN + B.Expression.BindTo(B.While, t => t.Condition) + B.RIGHT_PAREN + B.DO + B.Statement.BindTo(B.While, t => t.Body) ; B.For.Rule = B.FOR + B.LEFT_PAREN + B.LocalVariable.StarList(B.COMMA).BindTo(B.For, t => t.Init) + B.SEMICOLON + B.Expression.BindTo(B.For, t => t.Condition) + B.SEMICOLON + B.Assignment.StarList(B.COMMA).BindTo(B.For, t => t.Update) + B.RIGHT_PAREN + B.DO + B.Statement.BindTo(B.For, t => t.Body) ; #if SEPARATE_IFELSE B.If.Rule = B.IF + B.LEFT_PAREN + B.Expression.BindTo(B.If, t => t.Condition) + B.RIGHT_PAREN + B.THEN + B.Statement.BindTo(B.If, t => t.Body) ; B.IfElse.Rule = B.If.Copy(B.IfElse) + B.ELSE + B.Statement.BindTo(B.IfElse, t => t.ElseBody) ; #else B.If.Rule = B.IF + B.LEFT_PAREN + B.Expression.BindTo(B.If, t => t.Condition) + B.RIGHT_PAREN + B.THEN + B.Statement.BindTo(B.If, t => t.Body) + (B.ELSE + B.Statement).QRef().BindTo(B.If, t => t.ElseBody) ; #endif B.FunctionCall.Rule = B.FunctionReference.BindTo(B.FunctionCall, t => t.FunctionReference) + B.LEFT_PAREN + B.Argument.StarList(B.COMMA).BindTo(B.FunctionCall, t => t.Arguments) + B.RIGHT_PAREN ; B.Argument.Rule = B.Expression.BindTo(B.Argument, t => t.Expression) ; B.Write.Rule = B.WRITE + B.LEFT_PAREN + B.Expression.StarList(B.COMMA).BindTo(B.Write, t => t.Arguments) + B.RIGHT_PAREN ; B.WriteLn.Rule = B.WRITELN + B.LEFT_PAREN + B.Expression.StarList(B.COMMA).BindTo(B.WriteLn, t => t.Arguments) + B.RIGHT_PAREN ; B.Name.Rule = B.IDENTIFIER.BindTo(B.Name, t => t.Value); B.NameRef.Rule = B.IDENTIFIER.ConvertValue(_identifier => new NameRef(_identifier), _nameRef => _nameRef.Value); B.NamespaceName.Rule = B.IDENTIFIER .PlusList(B.DOT) .ConvertValue( _identifiers => new NameRef(string.Join(B.DOT.Text, _identifiers)), _nameRef => _nameRef.Value.Split(new string[] { B.DOT.Text }, StringSplitOptions.None) ); B.Expression.SetRuleOr( B.BinaryExpression, B.UnaryExpression, B.ConditionalTernaryExpression, B.NumberLiteral, B.DateLiteral, B.StringLiteral, B.BoolLiteral, B.ColorLiteral, B.FunctionCall, B.VariableReference, B.LEFT_PAREN + B.Expression + B.RIGHT_PAREN ); B.BinaryExpression.Rule = B.Expression.BindTo(B.BinaryExpression, t => t.Term1) + B.BinaryOperator.BindTo(B.BinaryExpression, t => t.Op) + B.Expression.BindTo(B.BinaryExpression, t => t.Term2) ; /* * NOTE: ImplyPrecedenceHere does not work properly, so we do not use it (it parsed operator NEG as operator POS, and omitted the expression after). * So we use ReduceHere instead, which means that unary operators has the highest precedence among operators when used inside a unary expressions. * */ B.UnaryExpression.Rule = B.UnaryOperator.BindTo(B.UnaryExpression, t => t.Op) + B.Expression.BindTo(B.UnaryExpression, t => t.Term) + ReduceHere() // this is needed for implying precedence (see note above) ; B.ConditionalTernaryExpression.Rule = B.Expression.BindTo(B.ConditionalTernaryExpression, t => t.Cond) + B.QUESTION_MARK + B.Expression.BindTo(B.ConditionalTernaryExpression, t => t.Term1) + B.COLON + B.Expression.BindTo(B.ConditionalTernaryExpression, t => t.Term2) ; var numberLiteralInfo = new NumberLiteralInfo() .AddSuffix("D", TypeCode.Double) .AddSuffix("M", TypeCode.Decimal) .AddPrefix("#b", NumberLiteralBase.Binary) .AddPrefix("#o", NumberLiteralBase.Octal) .AddPrefix("#x", NumberLiteralBase.Hexadecimal); B.NumberLiteral.Rule = TerminalFactoryS.CreateNumberLiteral <DE.NumberLiteral>(numberLiteralInfo); // B.NumberLiteral.Rule = TerminalFactoryS.CreateNumberLiteral().BindTo(B.NumberLiteral, t => t.Value); // B.NumberLiteral used to be a BnfiTermRecord B.StringLiteral.Rule = TerminalFactoryS.CreateStringLiteral(name: "stringliteral", startEndSymbol: "'").BindTo(B.StringLiteral, t => t.Value); B.BoolLiteral.Rule = B.BOOL_CONSTANT.BindTo(B.BoolLiteral, t => t.Value); B.ColorLiteral.Rule = B.COLOR_CONSTANT.BindTo(B.ColorLiteral, t => t.Value); B.DateLiteral.Rule = TerminalFactoryS.CreateDataLiteralDateTimeQuoted(name: "dateliteral", startEndSymbol: "$", dateTimeFormat: D.DateLiteral.Format).BindTo(B.DateLiteral, t => t.Value); B.BinaryOperator.Rule = B.ADD_OP | B.SUB_OP | B.MUL_OP | B.DIV_OP | B.POW_OP | B.MOD_OP | B.EQ_OP | B.NEQ_OP | B.LT_OP | B.LTE_OP | B.GT_OP | B.GTE_OP | B.AND_OP | B.OR_OP; B.UnaryOperator.Rule = B.POS_OP | B.NEG_OP | B.NOT_OP; B.Type.Rule = B.INTEGER_TYPE | B.REAL_TYPE | B.STRING_TYPE | B.CHAR_TYPE | B.BOOL_TYPE | B.COLOR_TYPE | B.DATE_TYPE; /* * NOTE: RegisterOperators in Irony is string-based, therefore it is impossible to specify different precedences * for binary '+' and unary '+', and for binary '-' and unary '-', so we encode the precedences of unary operators * into the grammar by specifying a ReduceHere() hint after unary expressions. * */ RegisterOperators(10, Associativity.Right, B.QUESTION_MARK, B.COLON); RegisterOperators(20, B.OR_OP); RegisterOperators(30, B.AND_OP); RegisterOperators(40, B.EQ_OP, B.NEQ_OP); RegisterOperators(50, B.LT_OP, B.LTE_OP, B.GT_OP, B.GTE_OP); RegisterOperators(60, B.ADD_OP, B.SUB_OP); RegisterOperators(70, B.MUL_OP, B.DIV_OP, B.MOD_OP); RegisterOperators(80, Associativity.Right, B.POW_OP); RegisterOperators(90, Associativity.Neutral, recurse: false, operators: new[] { B.NEG_OP, B.POS_OP, B.NOT_OP }); // NOTE: for the parser the unary operators precedences are encoded into the grammar, but for the unparser we have to specify the precedences // NOTE: we must not recurse, since NEG_OP and POS_OP has the same terminals as SUB_OP and ADD_OP, respectively ('-' and '+'). RegisterBracePair(B.LEFT_PAREN, B.RIGHT_PAREN); CommentTerminal DelimitedComment = new CommentTerminal("DelimitedComment", "(@", "@)"); CommentTerminal SingleLineComment = new CommentTerminal("SingleLineComment", "@@", Environment.NewLine, "\n", "\r"); NonGrammarTerminals.Add(DelimitedComment); NonGrammarTerminals.Add(SingleLineComment); }
public GrammarInfix() : base(new Domain()) { B = new BnfTerms(new TerminalFactoryS(this)); this.Root = B.Expression; B.Expression.SetRuleOr( B.BinaryExpression, B.UnaryExpression, B.ConditionalTernaryExpression, B.NumberLiteral, B.BoolLiteral, B.LEFT_PAREN + B.Expression + B.RIGHT_PAREN ); B.BinaryExpression.Rule = B.Expression.BindTo(B.BinaryExpression, t => t.Term1) + B.BinaryOperator.BindTo(B.BinaryExpression, t => t.Op) + B.Expression.BindTo(B.BinaryExpression, t => t.Term2) ; /* * NOTE: ImplyPrecedenceHere does not work properly, so we do not use it (it parsed operator NEG as operator POS, and omitted the expression after). * So we use ReduceHere instead, which means that unary operators has the highest precedence among operators when used inside a unary expressions. * */ B.UnaryExpression.Rule = B.UnaryOperator.BindTo(B.UnaryExpression, t => t.Op) + B.Expression.BindTo(B.UnaryExpression, t => t.Term) + ReduceHere() // this is needed for implying precedence (see note above) ; B.ConditionalTernaryExpression.Rule = B.Expression.BindTo(B.ConditionalTernaryExpression, t => t.Cond) + B.QUESTION_MARK + B.Expression.BindTo(B.ConditionalTernaryExpression, t => t.Term1) + B.COLON + B.Expression.BindTo(B.ConditionalTernaryExpression, t => t.Term2) ; var numberLiteralInfo = new NumberLiteralInfo() .AddPrefix("#b", NumberLiteralBase.Binary) .AddPrefix("#o", NumberLiteralBase.Octal) .AddPrefix("#x", NumberLiteralBase.Hexadecimal); B.NumberLiteral.Rule = TerminalFactoryS.CreateNumberLiteral <D.NumberLiteral>(numberLiteralInfo); B.BoolLiteral.Rule = B.BOOL_CONSTANT.BindTo(B.BoolLiteral, t => t.Value); B.BinaryOperator.Rule = B.ADD_OP | B.SUB_OP | B.MUL_OP | B.DIV_OP | B.POW_OP | B.MOD_OP | B.EQ_OP | B.NEQ_OP | B.LT_OP | B.LTE_OP | B.GT_OP | B.GTE_OP | B.AND_OP | B.OR_OP; B.UnaryOperator.Rule = B.POS_OP | B.NEG_OP | B.NOT_OP; /* * NOTE: RegisterOperators in Irony is string-based, therefore it is impossible to specify different precedences * for binary '+' and unary '+', and for binary '-' and unary '-', so we encode the precedences of unary operators * into the grammar by specifying a ReduceHere() hint after unary expressions. * */ RegisterOperators(10, Associativity.Right, B.QUESTION_MARK, B.COLON); RegisterOperators(20, B.OR_OP); RegisterOperators(30, B.AND_OP); RegisterOperators(40, B.EQ_OP, B.NEQ_OP); RegisterOperators(50, B.LT_OP, B.LTE_OP, B.GT_OP, B.GTE_OP); RegisterOperators(60, B.ADD_OP, B.SUB_OP); RegisterOperators(70, B.MUL_OP, B.DIV_OP, B.MOD_OP); RegisterOperators(80, Associativity.Right, B.POW_OP); RegisterOperators(90, Associativity.Neutral, recurse: false, operators: new[] { B.NEG_OP, B.POS_OP, B.NOT_OP }); // NOTE: for the parser the unary operators precedences are encoded into the grammar, but for the unparser we have to specify the precedences // NOTE: we must not recurse, since NEG_OP and POS_OP has the same terminals as SUB_OP and ADD_OP, respectively ('-' and '+'). RegisterBracePair(B.LEFT_PAREN, B.RIGHT_PAREN); }
internal BnfTerms(TerminalFactoryS TerminalFactoryS) { this.PROGRAM = TerminalFactoryS.CreateKeyTerm("program"); this.NAMESPACE = TerminalFactoryS.CreateKeyTerm("namespace"); this.BEGIN = TerminalFactoryS.CreateKeyTerm("{"); this.END = TerminalFactoryS.CreateKeyTerm("}"); this.WHILE = TerminalFactoryS.CreateKeyTerm("while"); this.FOR = TerminalFactoryS.CreateKeyTerm("for"); this.IF = TerminalFactoryS.CreateKeyTerm("if"); this.ELSE = TerminalFactoryS.CreateKeyTerm("else"); this.RETURN = TerminalFactoryS.CreateKeyTerm("return"); this.WRITE = TerminalFactoryS.CreateKeyTerm("Write"); this.WRITELN = TerminalFactoryS.CreateKeyTerm("WriteLn"); this.ASYNC = TerminalFactoryS.CreateKeyTerm("async", true); this.DOT = TerminalFactoryS.CreateKeyTerm("."); this.LET = TerminalFactoryS.CreateKeyTerm("="); this.SEMICOLON = TerminalFactoryS.CreateKeyTerm(";"); this.COLON = TerminalFactoryS.CreateKeyTerm(":"); this.COMMA = TerminalFactoryS.CreateKeyTerm(","); this.LEFT_PAREN = TerminalFactoryS.CreateKeyTerm("("); this.RIGHT_PAREN = TerminalFactoryS.CreateKeyTerm(")"); this.QUESTION_MARK = TerminalFactoryS.CreateKeyTerm("?"); this.ADD_OP = TerminalFactoryS.CreateKeyTerm("+", DE.BinaryOperator.Add); this.SUB_OP = TerminalFactoryS.CreateKeyTerm("-", DE.BinaryOperator.Sub); this.MUL_OP = TerminalFactoryS.CreateKeyTerm("*", DE.BinaryOperator.Mul); this.DIV_OP = TerminalFactoryS.CreateKeyTerm("/", DE.BinaryOperator.Div); this.POW_OP = TerminalFactoryS.CreateKeyTerm("^", DE.BinaryOperator.Pow); this.MOD_OP = TerminalFactoryS.CreateKeyTerm("%", DE.BinaryOperator.Mod); this.POS_OP = TerminalFactoryS.CreateKeyTerm("+", DE.UnaryOperator.Pos); this.NEG_OP = TerminalFactoryS.CreateKeyTerm("-", DE.UnaryOperator.Neg); this.EQ_OP = TerminalFactoryS.CreateKeyTerm("==", DE.BinaryOperator.Eq); this.NEQ_OP = TerminalFactoryS.CreateKeyTerm("<>", DE.BinaryOperator.Neq); this.LT_OP = TerminalFactoryS.CreateKeyTerm("<", DE.BinaryOperator.Lt); this.LTE_OP = TerminalFactoryS.CreateKeyTerm("<=", DE.BinaryOperator.Lte); this.GT_OP = TerminalFactoryS.CreateKeyTerm(">", DE.BinaryOperator.Gt); this.GTE_OP = TerminalFactoryS.CreateKeyTerm(">=", DE.BinaryOperator.Gte); this.AND_OP = TerminalFactoryS.CreateKeyTerm("&&", DE.BinaryOperator.And); this.OR_OP = TerminalFactoryS.CreateKeyTerm("||", DE.BinaryOperator.Or); this.NOT_OP = TerminalFactoryS.CreateKeyTerm("!", DE.UnaryOperator.Not); this.INTEGER_TYPE = TerminalFactoryS.CreateKeyTerm("int", D.Type.Integer); this.REAL_TYPE = TerminalFactoryS.CreateKeyTerm("double", D.Type.Real); this.STRING_TYPE = TerminalFactoryS.CreateKeyTerm("string", D.Type.String); this.CHAR_TYPE = TerminalFactoryS.CreateKeyTerm("char", D.Type.Char); this.BOOL_TYPE = TerminalFactoryS.CreateKeyTerm("bool", D.Type.Bool); this.COLOR_TYPE = TerminalFactoryS.CreateKeyTerm("color", D.Type.Color); this.DATE_TYPE = TerminalFactoryS.CreateKeyTerm("date", D.Type.Date); this.BOOL_CONSTANT = new BnfiTermConstant <bool>() { { "true", true }, { "false", false } }; this.COLOR_CONSTANT = new BnfiTermConstant <D.Color>() { { "color_black", D.Color.Black }, { "color_blue", D.Color.Blue }, { "color_brown", D.Color.Brown }, { "color_gray", D.Color.Gray }, { "color_green", D.Color.Green }, { "color_orange", D.Color.Orange }, { "color_red", D.Color.Red }, { "color_white", D.Color.White }, { "color_yellow", D.Color.Yellow } }; // NOTE: to parse keyterms with international characters properly we need to allow international characters in identifiers as well: // CreateCSharpIdentifier creates an identifier terminal that allows internation characters // this.IDENTIFIER = TerminalFactoryS.CreateIdentifier(); this.IDENTIFIER = TerminalFactory.CreateCSharpIdentifier("identifier").IntroIdentifier(); }