Exemplo n.º 1
0
        public void TestNumber_Python()
        {
            Parser parser; Token token;

            double eps = 0.0001;

            parser = TestHelper.CreateParser(TerminalFactory.CreatePythonNumber("Number"));

            //Simple integers and suffixes
            token = parser.ParseInput("123 ");
            CheckType(token, typeof(int));
            Assert.True(token.Details != null, "ScanDetails object not found in token.");
            Assert.True((int)token.Value == 123, "Failed to read int value");

            token = parser.ParseInput("123L ");
            CheckType(token, typeof(long));
            Assert.True((long)token.Value == 123, "Failed to read long value");

            //Hex representation
            token = parser.ParseInput("0x012 ");
            CheckType(token, typeof(int));
            Assert.True((int)token.Value == 0x012, "Failed to read hex int value");

            token = parser.ParseInput("0x012l "); //with small "L"
            CheckType(token, typeof(long));
            Assert.True((long)token.Value == 0x012, "Failed to read hex long value");

            //Floating point types
            token = parser.ParseInput("123.4 ");
            CheckType(token, typeof(double));
            Assert.True(Math.Abs((double)token.Value - 123.4) < eps, "Failed to read double value #1");

            token = parser.ParseInput("1234e-1 ");
            CheckType(token, typeof(double));
            Assert.True(Math.Abs((double)token.Value - 1234e-1) < eps, "Failed to read double value #2");

            token = parser.ParseInput("12.34e+01 ");
            CheckType(token, typeof(double));
            Assert.True(Math.Abs((double)token.Value - 123.4) < eps, "Failed to read double value  #3");

            token = parser.ParseInput("0.1234E3 ");
            CheckType(token, typeof(double));
            Assert.True(Math.Abs((double)token.Value - 123.4) < eps, "Failed to read double value  #4");

            token = parser.ParseInput(".1234 ");
            CheckType(token, typeof(double));
            Assert.True(Math.Abs((double)token.Value - 0.1234) < eps, "Failed to read double value with leading dot");

            token = parser.ParseInput("123. ");
            CheckType(token, typeof(double));
            Assert.True(Math.Abs((double)token.Value - 123.0) < eps, "Failed to read double value with trailing dot");

            //Big integer
            string sbig = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; //100 digits

            token = parser.ParseInput(sbig);
            Assert.True(token.Value.ToString() == sbig, "Failed to read big integer value");

            //Quick parse
            token = parser.ParseInput("1 ");
            CheckType(token, typeof(int));
            Assert.True(token.Details == null, "Quick parse test failed: ScanDetails object is found in token - quick parse path should produce this object.");
            Assert.True((int)token.Value == 1, "Failed to read quick-parse value");
        }
Exemplo n.º 2
0
        public MiaGrammar()
            : base(caseSensitive: true)
        {
            // 1. Terminals
            var number     = TerminalFactory.CreatePythonNumber("number");
            var identifier = TerminalFactory.CreatePythonIdentifier("identifier");
            //var propertyId = MiaTerminalFactory.CreatePropertyId("property");
            var varId   = MiaTerminalFactory.CreateVariableId("variable");
            var nounId  = MiaTerminalFactory.CreateNounId("noun");
            var verbId  = MiaTerminalFactory.CreateVerbId("verb");
            var comment = new CommentTerminal("comment", "//", "\n", "\r");

            //comment must to be added to NonGrammarTerminals list; it is not used directly in grammar rules,
            // so we add it to this list to let Scanner know that it is also a valid terminal.
            base.NonGrammarTerminals.Add(comment);
            var comma     = ToTerm(",");
            var colon     = ToTerm(":");
            var semicolon = ToTerm(";");
            var snippet1  = new StringLiteral("snippet");
            var snippet2  = new StringLiteral("snippet2");

            //snippet.AddStartEnd("{", "}", StringOptions.None);
            snippet1.AddStartEnd("{", "}", StringOptions.AllowsLineBreak);
            snippet2.AddStartEnd("{%", "%}", StringOptions.AllowsLineBreak);
            // 2. Non-terminals
            var Snippet        = new NonTerminal("Snippet");
            var Constituent    = new NonTerminal("Constituent");
            var Expr           = new NonTerminal("Expr");
            var Term           = new NonTerminal("Term");
            var BinExpr        = new NonTerminal("BinExpr");
            var ParExpr        = new NonTerminal("ParExpr");
            var UnExpr         = new NonTerminal("UnExpr");
            var UnOp           = new NonTerminal("UnOp", "unary-operator");
            var BinOp          = new NonTerminal("BinOp", "binary-operator");
            var ColonExpr      = new NonTerminal("ColonExpr", "ColonExpr");
            var CommaExpr      = new NonTerminal("CommaExpr", "CommaExpr");
            var PropertyExpr   = new NonTerminal("PropertyExpr", "PropertyExpr");
            var AssignmentStmt = new NonTerminal("AssignmentStmt");
            var Stmt           = new NonTerminal("Stmt");
            var ExtStmt        = new NonTerminal("ExtStmt");
            //
            var ReturnStmt = new NonTerminal("return");
            var PassStmt   = new NonTerminal("pass");
            var Block      = new NonTerminal("Block");
            var StmtList   = new NonTerminal("StmtList");
            //
            var DeclBlock    = new NonTerminal("DeclBlock");
            var DeclStmtList = new NonTerminal("DeclStmtList");

            var ParamList    = new NonTerminal("ParamList");
            var ArgList      = new NonTerminal("ArgList");
            var FunctionDef  = new NonTerminal("FunctionDef");
            var FunctionCall = new NonTerminal("FunctionCall");
            //
            var NamespaceDef = new NonTerminal("NamespaceDef");
            var BrainDef     = new NonTerminal("BrainDef");
            var ExpertDef    = new NonTerminal("ExpertDef");
            var MethodDef    = new NonTerminal("MethodDef");
            var PredicateDef = new NonTerminal("PredicateDef");
            var ClauseExpr   = new NonTerminal("ClauseExpr");
            var PropertyList = new NonTerminal("PropertyList");
            //
            var WhereActions   = new NonTerminal("WhereActions");
            var WhereAction    = new NonTerminal("WhereAction");
            var WhereStmt      = new NonTerminal("WhereStmt");
            var IfTrueStmt     = new NonTerminal("IfTrueStmt");
            var IfFalseStmt    = new NonTerminal("IfFalseStmt");
            var IfAllTrueStmt  = new NonTerminal("IfAllTrueStmt");
            var IfAllFalseStmt = new NonTerminal("IfAllFalseStmt");
            //
            var SelectStmt = new NonTerminal("SelectStmt");
            var CaseStmt   = new NonTerminal("CaseStmt");

            // 3. BNF rules
            //Expr.Rule = Term | UnExpr | BinExpr;
            Expr.Rule         = Term | UnExpr | BinExpr | PropertyExpr;
            Constituent.Rule  = number | ParExpr | nounId | varId | Snippet;
            Snippet.Rule      = snippet1 | snippet2;
            Term.Rule         = varId | nounId | ClauseExpr;
            ParExpr.Rule      = "(" + Expr + ")";
            UnExpr.Rule       = UnOp + Expr | UnOp + UnExpr;
            UnOp.Rule         = ToTerm("+") | "-" | "*" | "@" | "/" | "not";
            BinExpr.Rule      = Expr + BinOp + Expr;
            CommaExpr.Rule    = Expr + "," + Eos + Block;
            ColonExpr.Rule    = Expr + ":" + Eos + Block;
            PropertyExpr.Rule = Term + "`" + Term;
            BinOp.Rule        = ToTerm("&&") | "||" | "~=" | "==" | "->";

            AssignmentStmt.Rule = identifier + "=" + Expr;
            Stmt.Rule           = AssignmentStmt | Snippet | Expr | PassStmt | ReturnStmt | Empty;

            ReturnStmt.Rule = "return" + (Expr | Empty);
            PassStmt.Rule   = "pass";
            //Eos is End-Of-Statement token produced by CodeOutlineFilter
            Block.Rule     = Indent + StmtList + Dedent;
            DeclBlock.Rule = Indent + StmtList + Dedent;
            StmtList.Rule  = MakePlusRule(StmtList, ExtStmt);
            ExtStmt.Rule   =
                Stmt + Eos |
                ColonExpr |
                CommaExpr |
                NamespaceDef |
                BrainDef |
                ExpertDef |
                MethodDef |
                WhereStmt |
                PredicateDef |
                SelectStmt |
                CaseStmt;

            ParamList.Rule   = MakeStarRule(ParamList, comma, identifier);
            ArgList.Rule     = MakeStarRule(ArgList, comma, Expr);
            FunctionDef.Rule = "def" + identifier + "(" + ParamList + ")" + colon + Eos + Block;
            FunctionDef.NodeCaptionTemplate = "def #{1}(...)";
            FunctionCall.Rule = identifier + "(" + ArgList + ")";
            FunctionCall.NodeCaptionTemplate = "call #{0}(...)";
            //
            NamespaceDef.Rule = "namespace" + identifier + Eos + Block;
            BrainDef.Rule     = "brain" + identifier + Eos + Block;
            ExpertDef.Rule    = "expert" + identifier + Eos + Block;
            //MethodDef.Rule = "method" + identifier + "(" + (Expr | Empty) + ")" + Eos + Block;
            MethodDef.Rule    = ("method" + identifier + "(" + ArgList + ")" + Eos + Block) | ("method" + identifier + Eos + Block);
            PredicateDef.Rule = "predicate" + identifier + "(" + ParamList + ")" + Eos;
            //
            WhereActions.Rule   = MakePlusRule(WhereActions, WhereAction);
            WhereAction.Rule    = IfTrueStmt | IfFalseStmt | IfAllTrueStmt | IfAllFalseStmt;
            WhereStmt.Rule      = "where" + Eos + Block + WhereActions;
            IfTrueStmt.Rule     = "-->" + Eos + Block;
            IfFalseStmt.Rule    = "~->" + Eos + Block;
            IfAllTrueStmt.Rule  = "==>" + Eos + Block;
            IfAllFalseStmt.Rule = "~=>" + Eos + Block;
            //
            SelectStmt.Rule = "select" + Eos + Block;
            CaseStmt.Rule   = "case" + Snippet + Eos + Block;
            //
            PropertyList.Rule = MakeStarRule(PropertyList, comma, Expr);
            //
            ClauseExpr.Rule = verbId | (Constituent + verbId) | (verbId + Constituent) | (Constituent + verbId + Constituent);
            //
            //
            this.Root = StmtList;       // Set grammar root

            // 4. Token filters - created in a separate method CreateTokenFilters
            //    we need to add continuation symbol to NonGrammarTerminals because it is not used anywhere in grammar
            NonGrammarTerminals.Add(ToTerm(@"\"));

            // 5. Operators precedence
            //RegisterOperators(1, "+", "-");
            //RegisterOperators(2, "*", "/");
            //RegisterOperators(3, Associativity.Right, "**");

            // 6. Miscellaneous: punctuation, braces, transient nodes
            MarkPunctuation("(", ")", ":");
            RegisterBracePair("(", ")");
            //MarkTransient(Term, Expr, Stmt, ExtStmt, UnOp, BinOp, ExtStmt, ParExpr, Block);
            MarkTransient(Term, Expr, Stmt, UnOp, BinOp, ExtStmt, ParExpr, Block, Constituent, Snippet);

            // 7. Error recovery rule
            ExtStmt.ErrorRule     = SyntaxError + Eos;
            FunctionDef.ErrorRule = SyntaxError + Dedent;

            // 8. Syntax error reporting
            AddToNoReportGroup("(");
            AddToNoReportGroup(Eos);
            AddOperatorReportGroup("operator");

            // 9. Initialize console attributes
            ConsoleTitle    = "Mini-Python Console";
            ConsoleGreeting =
                @"Irony Sample Console for mini-Python.
 
   Supports a small sub-set of Python: assignments, arithmetic operators, 
   function declarations with 'def'. Supports big integer arithmetics.
   Supports Python indentation and line-joining rules, including '\' as 
   a line joining symbol. 

Press Ctrl-C to exit the program at any time.
";
            ConsolePrompt          = ">>>";
            ConsolePromptMoreInput = "...";

            // 10. Language flags
            //this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt;
            this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.SupportsBigInt;
        }//constructor
        // ROADMAP:
        // 1. Basic object-tree shit (atoms)
        // 2. Proc support
        // 3. Preprocessor
        public DreamGrammar()
            : base(caseSensitive: true)
        {
            // Thankfully, we get built-in pythonic numbers, which is exactly what we need.
            var NUMBER     = TerminalFactory.CreatePythonNumber("number");
            var IDENTIFIER = TerminalFactory.CreatePythonIdentifier("identifier");
            var STRING     = TerminalFactory.CreatePythonString("string"); // TODO:  May need to be custom.

            // Constant terminals
            var PROC   = ToTerm("proc");
            var VAR    = ToTerm("var");
            var RETURN = ToTerm("return");

            var COMMA = ToTerm(",");
            var SLASH = ToTerm("/");
            var PIPE  = ToTerm("|");

            #region Comment stuff

            // Dream uses both line comments and block comments.
            var lineComment = new CommentTerminal("lineComment", "//", "\n", "\r");

            // May or may not work, since BYOND permits nesting and most other languages don't.
            var blockComment = new CommentTerminal("blockComment", "/*", "*/");

            // From MiniPython example:
            // //comment must to be added to NonGrammarTerminals list; it is not used directly in grammar rules,
            // // so we add it to this list to let Scanner know that it is also a valid terminal.
            // However, with Dream, we may need to make them grammar terminals so we can handle nesting properly. - N3X
            base.NonGrammarTerminals.Add(lineComment);
            base.NonGrammarTerminals.Add(blockComment);

            // Needed for EOL escaping.
            base.NonGrammarTerminals.Add(ToTerm(@"\"));
            #endregion

            #region Non-Terminals
            // Blocks
            ////////////////////////////

            // procs
            var procblock       = new NonTerminal("procblock", "proc block");
            var procslash       = new NonTerminal("procslash");
            var procdef         = new NonTerminal("procdef", "proc definition");
            var procdefs        = new NonTerminal("procdefs");
            var procdef_no_path = new NonTerminal("procdef_no_path", "proc definition (sans path)");
            var procdecl        = new NonTerminal("procdecl");
            var procchildren    = new NonTerminal("procchildren", "proc children");

            // Atoms
            var atomdef      = new NonTerminal("atomdef");
            var atomblock    = new NonTerminal("atomblock", "atom declaration");
            var atomchildren = new NonTerminal("atomchildren", "atom declaration");
            var atomchild    = new NonTerminal("atomchild", "atom child");

            // Path stuff
            var path      = new NonTerminal("path");
            var abspath   = new NonTerminal("abspath", "absolute path");
            var relpath   = new NonTerminal("relpath", "relative path");
            var pathslash = new NonTerminal("pathslash");

            // Statements
            /////////////////////////////

            // Variable declaration
            var vardefs = new NonTerminal("vardefs");
            var vardef  = new NonTerminal("vardef");
            var inline_vardef_no_default = new NonTerminal("inline_vardef_no_default");
            var inline_vardef            = new NonTerminal("inline_vardef");
            var varblock = new NonTerminal("varblock");

            // Parameters
            var param      = new NonTerminal("param", "parameter" /*, typeof(OpenBYOND.Dream.AST.ParameterNode)*/);
            var parameters = new NonTerminal("parameters");
            var paramlist  = new NonTerminal("paramlist", "parameter list", typeof(ParamListNode));

            // Primitives (Identifiers won't work because of the "anything in <list>" rule.)
            var primitive     = new NonTerminal("primitive");
            var primitivelist = new NonTerminal("primitivelist", "primitive list");

            // Expressions
            var const_expression      = new NonTerminal("const_expression");
            var expression            = new NonTerminal("expression");
            var expressions           = new NonTerminal("expressions");
            var assignable_expression = new NonTerminal("assignable_expression");
            var assignment            = new NonTerminal("assignment");
            var operations            = new NonTerminal("operations");

            // Statements
            var return_stmt = new NonTerminal("return_stmt");

            var script     = new NonTerminal("script", "script root", typeof(StatementListNode));
            var declblocks = new NonTerminal("declblocks", "declarative blocks");

            // Easier on the eyes.
            var INDENT = Indent;
            var DEDENT = Dedent;
            #endregion

            #region BNF Rules

            #region Type Paths
            // <path> ::= <abspath> | <relpath>
            path.Rule = abspath | relpath;

            // <relpath> ::= <identifier>
            //             | <relpath> '/' <identifier>
            relpath.Rule = IDENTIFIER
                           | relpath + SLASH + IDENTIFIER;

            // <abspath> ::= '/' <relpath>
            //             | <abspath> '/' <identifier>
            abspath.Rule = SLASH + relpath
                           | abspath + SLASH + IDENTIFIER;

            // <pathslash> ::= <path> '/'
            pathslash.Rule = path + SLASH;
            #endregion

            #region Blocks (atoms, procs, if, etc)
            // <atomblock> ::= <path> INDENT <atomchildren> DEDENT
            atomblock.Rule = path + INDENT + atomchildren + DEDENT;

            // <atomchildren> ::= <atomchild>*
            atomchildren.Rule = MakeStarRule(atomchildren, atomchild);

            // <atomchild> ::= <vardecl>
            //               | <atomblock>
            //               | <procblock>
            //               | <varblock>
            atomchild.Rule = vardef
                             | atomblock
                             | procblock
                             | varblock
            ;

            // <procblock> ::= PROC INDENT <procdefs> DEDENT
            procblock.Rule = PROC + INDENT + procdefs + DEDENT;

            // <procdefs> ::= <procdef_no_path>+
            procdefs.Rule = MakePlusRule(procdefs, procdef_no_path);

            // <declblocks> ::= <procblock>
            //                | <atomblock>
            declblocks.Rule = atomblock
                              | procblock
                              | procdecl
                              | procdef
                              | varblock
            ;
            #endregion

            #region Variable stuff
            // <vardef> ::= <path> <varblock>
            //            | <varblock>
            //            | <inline_vardef>
            vardef.Rule = path + varblock
                          | varblock
                          | inline_vardef
            ;

            // <vardefs> ::= <vardef>+
            vardefs.Rule = MakePlusRule(vardefs, vardef);

            // var/honk is basically
            // VAR path(/) identifier(honk)
            // <inline_vardef_no_default> ::= VAR <abspath> '/' IDENTIFIER
            //                              | VAR '/' IDENTIFIER
            inline_vardef_no_default.Rule = VAR + abspath
            ;
            // <inline_vardef> ::= inline_vardef_no_default
            //                   | inline_vardef_no_default '='
            inline_vardef.Rule = inline_vardef_no_default
                                 | inline_vardef_no_default + "=" + const_expression
            ;

            // <varblock> ::= VAR INDENT <vardefs> DEDENT
            varblock.Rule = VAR + INDENT + vardefs + DEDENT;
            #endregion

            #region Proc stuff
            // <parameters> ::= '(' <paramlist> ')'
            parameters.Rule = ToTerm("(") + paramlist + ")";

            // <paramlist> ::= <param>*
            paramlist.Rule = MakeStarRule(paramlist, COMMA, param);

            // This is probably one of the worst parts about Dream. This shit is an absolute mess. - N3X
            // <param> ::= <inline_vardef>                          // var/type/blah [=blah]
            //           | <identifier>                       // blah
            //           | <inline_vardef_no_default> 'as' <primitivelist> // var/blah as obj|mob
            //           | <identifier> 'as' <primitivelist>  // blah as obj|mob
            param.Rule = inline_vardef
                         | IDENTIFIER
                         | inline_vardef_no_default + "as" + primitivelist
                         | IDENTIFIER + "as" + primitivelist
            ;

            // <procdef> ::= <path> <parameters> INDENT <expressions> DEDENT
            procdef.Rule = path + parameters + INDENT + expressions + DEDENT;

            // <procdef_no_path> ::= IDENTIFIER <parameters> INDENT <expressions> DEDENT
            procdef_no_path.Rule = IDENTIFIER + parameters + INDENT + expressions + DEDENT;

            // <procslash> ::= PROC SLASH
            procslash.Rule = PROC + SLASH;

            // <procdecl> ::= <pathslash> <procslash> <procdef_no_path>
            //              | <pathslash> <procblock>
            //              | <procblock>
            procdecl.Rule = pathslash + procslash + procdef_no_path
                            | pathslash + procblock
                            | procblock
            ;
            #endregion

            #region Expressions
            // Note:  this gets particularly hairy.

            // <const_expression> ::= NUMBER
            //                      | STRING
            //                      | '(' <const_expression> ')'
            //                      | <operations>
            const_expression.Rule = NUMBER
                                    | STRING
                                    | "(" + const_expression + ")"
                                    | operations
            ;

            // <operations> ::= <const_expression> "*" <const_expression>
            //                | <const_expression> "/" <const_expression>
            //                | <const_expression> "%" <const_expression>
            //                | <const_expression> "+" <const_expression>
            //                | <const_expression> "-" <const_expression>
            operations.Rule = const_expression + "*" + const_expression
                              | const_expression + "/" + const_expression
                              | const_expression + "%" + const_expression
                              | const_expression + "+" + const_expression
                              | const_expression + "-" + const_expression
            ;

            // <expression> ::= <assignment>
            //                | <inline_vardef>
            //                | <return_stmt>
            expression.Rule = assignment
                              | inline_vardef
                              | return_stmt
            ;

            // <expressions> ::= <expression>*
            expressions.Rule = MakeStarRule(expressions, expression);

            // <assignable_expression> ::= <const_expression>
            //                           | IDENTIFIER
            //                           | STRING
            assignable_expression.Rule = const_expression
                                         | IDENTIFIER
                                         | STRING
            ;

            // <assignment> ::= IDENTIFIER '=' <assignable_expression>
            assignment.Rule = IDENTIFIER + "=" + assignable_expression;

            // <return_stmt> ::= RETURN const_expression
            return_stmt.Rule = RETURN + const_expression;
            #endregion

            // Okay, this is apparently the right way to do it. - N3X
            primitive.Rule = ToTerm("obj") | "mob" | "turf"/*|"anything" + "in" + list*/
            ;

            // <primitivelist> ::= <primitive>+ (| seperator)
            primitivelist.Rule = MakePlusRule(primitivelist, PIPE, primitive);

            // <paramlist> ::= <parameter>*
            paramlist.Rule = MakeStarRule(paramlist, COMMA, param);

            // <script> ::= <declblocks>*
            script.Rule = declblocks;
            this.Root   = script;
            #endregion
            AddToNoReportGroup(Eos);

            this.MarkReservedWords("break", "continue", "else", "for", "if", "return", "while", "proc");

            this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt;
        }
Exemplo n.º 4
0
        public MiniPythonGrammar() : base(caseSensitive: true)
        {
            // 1. Terminals
            var number     = TerminalFactory.CreatePythonNumber("number");
            var identifier = TerminalFactory.CreatePythonIdentifier("identifier");
            var comment    = new CommentTerminal("comment", "#", "\n", "\r");

            //comment must to be added to NonGrammarTerminals list; it is not used directly in grammar rules,
            // so we add it to this list to let Scanner know that it is also a valid terminal.
            base.NonGrammarTerminals.Add(comment);
            var comma = ToTerm(",");
            var colon = ToTerm(":");

            // 2. Non-terminals
            var Expr           = new NonTerminal("Expr");
            var Term           = new NonTerminal("Term");
            var BinExpr        = new NonTerminal("BinExpr", typeof(BinaryOperationNode));
            var ParExpr        = new NonTerminal("ParExpr");
            var UnExpr         = new NonTerminal("UnExpr", typeof(UnaryOperationNode));
            var UnOp           = new NonTerminal("UnOp", "operator");
            var BinOp          = new NonTerminal("BinOp", "operator");
            var AssignmentStmt = new NonTerminal("AssignmentStmt", typeof(AssignmentNode));
            var Stmt           = new NonTerminal("Stmt");
            var ExtStmt        = new NonTerminal("ExtStmt");
            //Just as a test for NotSupportedNode
            var ReturnStmt = new NonTerminal("return", typeof(NotSupportedNode));
            var Block      = new NonTerminal("Block");
            var StmtList   = new NonTerminal("StmtList", typeof(StatementListNode));

            var ParamList    = new NonTerminal("ParamList", typeof(ParamListNode));
            var ArgList      = new NonTerminal("ArgList", typeof(ExpressionListNode));
            var FunctionDef  = new NonTerminal("FunctionDef", typeof(FunctionDefNode));
            var FunctionCall = new NonTerminal("FunctionCall", typeof(FunctionCallNode));


            // 3. BNF rules
            Expr.Rule           = Term | UnExpr | BinExpr;
            Term.Rule           = number | ParExpr | identifier | FunctionCall;
            ParExpr.Rule        = "(" + Expr + ")";
            UnExpr.Rule         = UnOp + Term;
            UnOp.Rule           = ToTerm("+") | "-";
            BinExpr.Rule        = Expr + BinOp + Expr;
            BinOp.Rule          = ToTerm("+") | "-" | "*" | "/" | "**";
            AssignmentStmt.Rule = identifier + "=" + Expr;
            Stmt.Rule           = AssignmentStmt | Expr | ReturnStmt | Empty;
            ReturnStmt.Rule     = "return" + Expr; //Not supported for execution! - we associate NotSupportedNode with ReturnStmt
            //Eos is End-Of-Statement token produced by CodeOutlineFilter
            ExtStmt.Rule  = Stmt + Eos | FunctionDef;
            Block.Rule    = Indent + StmtList + Dedent;
            StmtList.Rule = MakePlusRule(StmtList, ExtStmt);

            ParamList.Rule   = MakeStarRule(ParamList, comma, identifier);
            ArgList.Rule     = MakeStarRule(ArgList, comma, Expr);
            FunctionDef.Rule = "def" + identifier + "(" + ParamList + ")" + colon + Eos + Block;
            FunctionDef.NodeCaptionTemplate = "def #{1}(...)";
            FunctionCall.Rule = identifier + "(" + ArgList + ")";
            FunctionCall.NodeCaptionTemplate = "call #{0}(...)";

            this.Root = StmtList; // Set grammar root

            // 4. Token filters - created in a separate method CreateTokenFilters
            //    we need to add continuation symbol to NonGrammarTerminals because it is not used anywhere in grammar
            NonGrammarTerminals.Add(ToTerm(@"\"));

            // 5. Operators precedence
            RegisterOperators(1, "+", "-");
            RegisterOperators(2, "*", "/");
            RegisterOperators(3, Associativity.Right, "**");

            // 6. Miscellaneous: punctuation, braces, transient nodes
            MarkPunctuation("(", ")", ":");
            RegisterBracePair("(", ")");
            MarkTransient(Term, Expr, Stmt, ExtStmt, UnOp, BinOp, ExtStmt, ParExpr, Block);

            // 7. Error recovery rule
            ExtStmt.ErrorRule     = SyntaxError + Eos;
            FunctionDef.ErrorRule = SyntaxError + Dedent;

            // 8. Syntax error reporting
            AddToNoReportGroup("(");
            AddToNoReportGroup(Eos);
            AddOperatorReportGroup("operator");

            // 9. Initialize console attributes
            ConsoleTitle    = "Mini-Python Console";
            ConsoleGreeting =
                @"Irony Sample Console for mini-Python.
 
   Supports a small sub-set of Python: assignments, arithmetic operators, 
   function declarations with 'def'. Supports big integer arithmetics.
   Supports Python indentation and line-joining rules, including '\' as 
   a line joining symbol. 

Press Ctrl-C to exit the program at any time.
";
            ConsolePrompt          = ">>>";
            ConsolePromptMoreInput = "...";

            // 10. Language flags
            this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt;
        }//constructor
Exemplo n.º 5
0
        public Gramatica() : base(true)
        {
            #region INSTRUCCION de TERMINALES
            NumberLiteral numero = TerminalFactory.CreatePythonNumber("numero");
            //NumberLiteral numero = new NumberLiteral("numero");
            IdentifierTerminal identificador = TerminalFactory.CreatePythonIdentifier("identificador");
            StringLiteral      cadena        = new StringLiteral("cadena", "\"", StringOptions.AllowsAllEscapes);
            StringLiteral      caracter      = new StringLiteral("caracter", "\'", StringOptions.IsChar);

            #region Palabras reservadas
            KeyTerm pr_int    = ToTerm("int"),
                    pr_double = ToTerm("double"),
                    pr_char   = ToTerm("char"),
                    pr_bool   = ToTerm("boolean"),
                    pr_void   = ToTerm("void"),
                    pr_String = ToTerm("String"),

                    Treturn   = ToTerm("return"),
                    __init__  = ToTerm("__init__"),
                    Tbreak    = ToTerm("break"),
                    Tcontinue = ToTerm("continue"),
                    Tif       = ToTerm("if"),
                    Telse     = ToTerm("else"),
                    Twhile    = ToTerm("while"),
                    Tclass    = ToTerm("class"),
                    Tnone     = ToTerm("None"),
                    Tassert   = ToTerm("assert"),
                    Tasync    = ToTerm("async"),
                    Tawait    = ToTerm("await"),
                    Tdef      = ToTerm("def"),
                    Tdel      = ToTerm("del"),
                    Tfor      = ToTerm("for"),
                    Tfrom     = ToTerm("from"),
                    Tglobal   = ToTerm("global"),
                    Timport   = ToTerm("import"),
                    Tin       = ToTerm("in"),
                    Tis       = ToTerm("is"),
                    Tpass     = ToTerm("pass"),
                    Traise    = ToTerm("raise"),
                    Twith     = ToTerm("with"),
                    Tnonlocal = ToTerm("nonlocal"),
                    Telif     = ToTerm("elif"),
                    Tprint    = ToTerm("print");

            MarkReservedWords("int", "double", "char", "bool", "String", "void", "return",
                              "break", "continue", "if", "else", "while", "class", "print",
                              "None", "assert", "async", "await", "def", "del", "elif", "for", "from", "global",
                              "import", "in", "is", "nonlocal", "pass", "raise", "with");
            #endregion

            #region Operadores y simbolos
            Terminal ptcoma        = ToTerm(";"),
                     coma          = ToTerm(","),
                     punto         = ToTerm("."),
                     dospts        = ToTerm(":"),
                     parizq        = ToTerm("("),
                     parder        = ToTerm(")"),
                     corizq        = ToTerm("["),
                     corder        = ToTerm("]"),
                     llaizq        = ToTerm("{"),
                     llader        = ToTerm("}"),
                     signo_mas     = ToTerm("+"),
                     signo_menos   = ToTerm("-"),
                     signo_por     = ToTerm("*"),
                     signo_mod     = ToTerm("%"),
                     signo_div     = ToTerm("/"),
                     signo_piso    = ToTerm("//"),
                     signo_pot     = ToTerm("^"),
                     igual_que     = ToTerm("=="),
                     diferente_que = ToTerm("!="),
                     menor_que     = ToTerm("<"),
                     menor_igual   = ToTerm("<="),
                     mayor_que     = ToTerm(">"),
                     mayor_igual   = ToTerm(">="),
                     pr_or         = ToTerm("or"),
                     pr_and        = ToTerm("and"),
                     pr_not        = ToTerm("not"),
                     pr_true       = ToTerm("true", "True"),
                     pr_false      = ToTerm("false", "False"),
                     igual         = ToTerm("=");
            #endregion

            #region Comentarios
            CommentTerminal comentarioMultilinea = new CommentTerminal("comentarioMultiLinea", "/*", "*/");
            base.NonGrammarTerminals.Add(comentarioMultilinea);
            CommentTerminal comentarioUnilinea = new CommentTerminal("comentarioUniLinea", "#", "\n", "\r\n");
            base.NonGrammarTerminals.Add(comentarioUnilinea);
            #endregion

            #endregion

            #region INSTRUCCION de NO TERMINALES
            NonTerminal S                 = new NonTerminal("S");
            NonTerminal EXPRESION         = new NonTerminal("EXPRESION");
            NonTerminal DECLARACION       = new NonTerminal("DECLARACION");
            NonTerminal FunctionDef       = new NonTerminal("FunctionDef");
            NonTerminal ParamList         = new NonTerminal("ParamList");
            NonTerminal Block             = new NonTerminal("Block");
            NonTerminal LLAMADA           = new NonTerminal("LLAMADA");
            NonTerminal ASIGNACION        = new NonTerminal("ASIGNACION");
            NonTerminal INSTRUCCION       = new NonTerminal("INSTRUCCION");
            NonTerminal DeclaracionLista  = new NonTerminal("DeclaracionLista");
            NonTerminal ReturnDeclaracion = new NonTerminal("ReturnDeclaracion");
            NonTerminal ExtDeclaracion    = new NonTerminal("ExtDeclaracion");
            NonTerminal ArgList           = new NonTerminal("ArgList");
            NonTerminal CLASES            = new NonTerminal("CLASES");
            NonTerminal CLASE             = new NonTerminal("CLASE");
            NonTerminal ClaseDef          = new NonTerminal("ClaseDef");
            NonTerminal LISTAASIGNACION   = new NonTerminal("LISTAASIGNACION");
            NonTerminal SENT_PRINT        = new NonTerminal("SENT_PRINT");
            NonTerminal LISTAEXPRE        = new NonTerminal("LISTAEXPRE");
            NonTerminal INI_ARRAY         = new NonTerminal("INI_ARRAY");
            NonTerminal B                 = new NonTerminal("B");
            NonTerminal LISTACORCHE       = new NonTerminal("LISTACORCHE");
            NonTerminal CORCHETES         = new NonTerminal("CORCHETES");
            NonTerminal TIPO              = new NonTerminal("TIPO");
            NonTerminal SENT_IF           = new NonTerminal("SENT_IF");


            #endregion

            #region Gramatica

            S.Rule = CLASES;

            CLASES.Rule = MakePlusRule(CLASES, CLASE);

            CLASE.Rule = INSTRUCCION
                         | ClaseDef;

            ClaseDef.Rule = Tclass + identificador + dospts + Eos + Block;

            DeclaracionLista.Rule = MakePlusRule(DeclaracionLista, ExtDeclaracion);

            ExtDeclaracion.Rule = INSTRUCCION
                                  | FunctionDef;

            FunctionDef.Rule = Tdef + TIPO + identificador + parizq + ParamList + parder + dospts + Eos + Block
                               | Tdef + __init__ + parizq + ParamList + parder + dospts + Eos + Block;

            ParamList.Rule = MakeStarRule(ParamList, coma, identificador);

            Block.Rule = Indent + DeclaracionLista + Dedent;

            INSTRUCCION.Rule = ASIGNACION + Eos
                               | DECLARACION + Eos
                               | SENT_PRINT + Eos
                               | SENT_IF
                               | LLAMADA + Eos
                               | ReturnDeclaracion + Eos;

            SENT_PRINT.Rule = Tprint + parizq + ArgList + parder;

            SENT_IF.Rule = Tif + EXPRESION + dospts + Eos + Block
                           | Tif + EXPRESION + dospts + Eos + Block + Telse + dospts + Eos + Block;

            DECLARACION.Rule = TIPO + identificador + igual + EXPRESION
                               | TIPO + identificador
                               | identificador + identificador
                               | Tnonlocal + identificador
                               | Tglobal + identificador;

            ASIGNACION.Rule = LISTAASIGNACION + igual + EXPRESION;

            LISTAASIGNACION.Rule = LISTAASIGNACION + punto + LISTAASIGNACION
                                   | identificador
                                   | identificador + parizq + ArgList + parder;

            INI_ARRAY.Rule = llaizq + B + llader;

            B.Rule = MakePlusRule(B, EXPRESION);

            LISTACORCHE.Rule = MakePlusRule(LISTACORCHE, CORCHETES);
            CORCHETES.Rule   = corizq + corder;

            EXPRESION.Rule =
                INI_ARRAY
                | LISTACORCHE
                | cadena
                | caracter
                | identificador
                | identificador + parizq + ArgList + parder
                | numero
                | EXPRESION + punto + EXPRESION
                | EXPRESION + Tis + EXPRESION
                | EXPRESION + Tin + EXPRESION
                | EXPRESION + signo_mas + EXPRESION
                | EXPRESION + signo_menos + EXPRESION
                | EXPRESION + signo_por + EXPRESION
                | EXPRESION + signo_div + EXPRESION
                | EXPRESION + signo_mod + EXPRESION
                | EXPRESION + signo_piso + EXPRESION
                | EXPRESION + mayor_que + EXPRESION
                | EXPRESION + mayor_igual + EXPRESION
                | EXPRESION + menor_que + EXPRESION
                | EXPRESION + menor_igual + EXPRESION
                | EXPRESION + igual_que + EXPRESION
                | EXPRESION + diferente_que + EXPRESION
                | EXPRESION + pr_or + EXPRESION
                | EXPRESION + pr_and + EXPRESION
                | signo_menos + EXPRESION
                | pr_not + EXPRESION;

            ReturnDeclaracion.Rule = Treturn + EXPRESION;

            LLAMADA.Rule = LISTAASIGNACION;

            ArgList.Rule = MakeStarRule(ArgList, coma, EXPRESION);

            TIPO.Rule = pr_int
                        | pr_bool
                        | pr_char
                        | pr_double
                        | pr_int
                        | pr_String
                        | pr_void
                        | Tnone;
            #endregion

            #region precedencia
            RegisterOperators(1, Associativity.Right, igual);
            RegisterOperators(2, Associativity.Left, pr_or);
            RegisterOperators(4, Associativity.Left, pr_and);
            RegisterOperators(5, Associativity.Left, igual_que, diferente_que);
            RegisterOperators(6, Associativity.Left, Tis, Tin, mayor_que, menor_que, mayor_igual, menor_igual);
            RegisterOperators(7, Associativity.Left, signo_mas, signo_menos);
            RegisterOperators(8, Associativity.Left, signo_por, signo_div, signo_mod, signo_piso);
            RegisterOperators(9, Associativity.Right, signo_pot);
            RegisterOperators(10, Associativity.Right, pr_not);
            RegisterOperators(11, Associativity.Left, punto);
            RegisterOperators(12, Associativity.Neutral, parizq, parder);
            #endregion

            ExtDeclaracion.ErrorRule = SyntaxError + Eos;
            FunctionDef.ErrorRule    = SyntaxError + Dedent;
            AddToNoReportGroup(parizq);
            AddToNoReportGroup(Eos);

            NonGrammarTerminals.Add(ToTerm(@"\"));
            MarkPunctuation(parizq, parder, llaizq, llader, ptcoma, dospts, coma, igual, punto);
            this.Root = S;
        }