Beispiel #1
0
        public ScriptdotnetGrammar(bool expressionGrammar)
        {
            #region 1. Terminals
              NumberLiteral n = TerminalFactory.CreateCSharpNumber("number");
              IdentifierTerminal v = CreateScriptNetIdentifier("Identifier");
              Terminal s = CreateScriptNetString("string");

              Terminal @is = Symbol("is");
              Terminal dot = Symbol(".", "dot");
              Terminal less = Symbol("<");
              Terminal greater = Symbol(">");
              Terminal arrow = Symbol("->");
              Terminal LSb = Symbol("[");
              Terminal RSb = Symbol("]");
              Terminal LCb = Symbol("(");
              Terminal RCb = Symbol(")");
              Terminal RFb = Symbol("}");
              Terminal LFb = Symbol("{");
              Terminal LMb = Symbol("<!");
              Terminal RMb = Symbol("!>");
              Terminal LGb = Symbol("<|");
              Terminal RGb = Symbol("|>");
              Terminal comma = Symbol(",");
              Terminal semicolon = Symbol(";");
              Terminal colon = Symbol(":");
              #endregion

              #region 2. Non-terminals
              #region 2.1 Expressions
              NonTerminal Expr = new NonTerminal("Expr", typeof(ScriptExpr));
              NonTerminal ConstExpr = new NonTerminal("ConstExpr", typeof(ScriptConstExpr));
              NonTerminal BinExpr = new NonTerminal("BinExpr", typeof(ScriptBinExpr));
              NonTerminal UnaryExpr = new NonTerminal("UnaryExpr", typeof(ScriptUnaryExpr));
              NonTerminal AssignExpr = new NonTerminal("AssignExpr", typeof(ScriptAssignExpr));
              NonTerminal TypeConvertExpr = new NonTerminal("TypeConvertExpr", typeof(ScriptTypeConvertExpr));
              NonTerminal IsExpr = new NonTerminal("IsExpr", typeof(ScriptIsExpr));
              NonTerminal MetaExpr = new NonTerminal("MetaExpr", typeof(ScriptMetaExpr));
              NonTerminal FuncDefExpr = new NonTerminal("FuncDefExpr", typeof(ScriptFunctionDefinition));  //typeof(ScriptFunctionDefExpression));

              NonTerminal TypeExpr = new NonTerminal("TypeExpr", typeof(ScriptTypeExpr));
              NonTerminal TypeConstructor = new NonTerminal("TypeConstructor", typeof(ScriptTypeConstructor));
              NonTerminal FunctionCall = new NonTerminal("FunctionCall", typeof(ScriptFunctionCall));
              NonTerminal ArrayResolution = new NonTerminal("ArrayResolution", typeof(ScriptArrayResolution));

              NonTerminal BinOp = new NonTerminal("BinOp");
              NonTerminal LUnOp = new NonTerminal("LUnOp");
              NonTerminal RUnOp = new NonTerminal("RUnOp");

              NonTerminal ArrayConstructor = new NonTerminal("ArrayConstructor", typeof(ScriptArrayConstructor));
              NonTerminal MObjectConstructor = new NonTerminal("MObjectConstructor", typeof(ScriptMObject));
              NonTerminal MObjectPart = new NonTerminal("MObjectPart", typeof(ScriptMObjectPart));
              NonTerminal MObjectParts = new NonTerminal("MObjectPart", typeof(ScriptAst));

              NonTerminal TypeList = new NonTerminal("TypeList", typeof(ScriptTypeExprList));
              #endregion

              #region 2.2 QualifiedName
              //Expression List:  expr1, expr2, expr3, ..
              NonTerminal ExprList = new NonTerminal("ExprList", typeof(ScriptExprList));

              //A name in form: a.b.c().d[1,2].e ....
              NonTerminal NewStmt = new NonTerminal("NewStmt", typeof(ScriptNewStmt));
              NonTerminal NewArrStmt = new NonTerminal("NewArrStmt", typeof(ScriptNewArrStmt));
              NonTerminal QualifiedName = new NonTerminal("QualifiedName", typeof(ScriptQualifiedName));
              NonTerminal GenericsPostfix = new NonTerminal("GenericsPostfix", typeof(ScriptGenericsPostfix));

              NonTerminal GlobalList = new NonTerminal("GlobalList", typeof(ScriptGlobalList));
              #endregion

              #region 2.3 Statement
              NonTerminal Condition = new NonTerminal("Condition", typeof(ScriptCondition));
              NonTerminal Statement = new NonTerminal("Statement", typeof(ScriptStatement));

              NonTerminal IfStatement = new NonTerminal("IfStatement", typeof(ScriptIfStatement));
              NonTerminal WhileStatement = new NonTerminal("WhileStatement", typeof(ScriptWhileStatement));
              NonTerminal ForStatement = new NonTerminal("ForStatement", typeof(ScriptForStatement));
              NonTerminal ForEachStatement = new NonTerminal("ForEachStatement", typeof(ScriptForEachStatement));
              NonTerminal OptionalExpression = new NonTerminal("OptionalExpression", typeof(ScriptExpr));
              NonTerminal SwitchStatement = new NonTerminal("SwitchStatement", typeof(ScriptStatement));
              NonTerminal SwitchStatements = new NonTerminal("SwitchStatements", typeof(ScriptSwitchStatement));
              NonTerminal SwitchCaseStatement = new NonTerminal("SwitchCaseStatement", typeof(ScriptSwitchCaseStatement));
              NonTerminal SwitchDefaultStatement = new NonTerminal("SwitchDefaultStatement", typeof(ScriptSwitchDefaultStatement));
              NonTerminal UsingStatement = new NonTerminal("UsingStatement", typeof(ScriptUsingStatement));
              NonTerminal TryCatchFinallyStatement = new NonTerminal("TryCatchFinallyStatement", typeof(ScriptTryCatchFinallyStatement));
              NonTerminal FlowControlStatement = new NonTerminal("FlowControl", typeof(ScriptFlowControlStatement));
              NonTerminal ExprStatement = new NonTerminal("ExprStatement", typeof(ScriptStatement));

              //Block
              NonTerminal BlockStatement = new NonTerminal("BlockStatement", typeof(ScriptStatement));
              NonTerminal Statements = new NonTerminal("Statements(Compound)", typeof(ScriptCompoundStatement));
              #endregion

              #region 2.4 Program and Functions
              NonTerminal Prog = new NonTerminal("Prog", typeof(ScriptProg));
              NonTerminal Element = new NonTerminal("Element", typeof(ScriptAst));
              NonTerminal Elements = new NonTerminal("Elements", typeof(ScriptElements));
              NonTerminal FuncDef = new NonTerminal("FuncDef", typeof(ScriptFunctionDefinition));
              NonTerminal FuncContract = new NonTerminal("FuncContract", typeof(ScriptFuncContract));
              NonTerminal ParameterList = new NonTerminal("ParamaterList", typeof(ScriptFuncParameters));

              NonTerminal FuncContractPre = new NonTerminal("Pre Conditions", typeof(ScriptFuncContractPre));
              NonTerminal FuncContractPost = new NonTerminal("Post Conditions", typeof(ScriptFuncContractPost));
              NonTerminal FuncContractInv = new NonTerminal("Invariant Conditions", typeof(ScriptFuncContractInv));
              #endregion

              #endregion

              #region 3. BNF rules
              #region 3.1 Expressions
              ConstExpr.Rule = Symbol("true")
                      | "false"
                      | "null"
                      | s
                      | n;

              BinExpr.Rule = Expr + BinOp + Expr
                     | IsExpr;

              UnaryExpr.Rule = LUnOp + Expr;

              IsExpr.Rule = Expr + @is + TypeExpr;

              TypeConvertExpr.Rule = LCb + Expr + RCb + Expr.Q();

              AssignExpr.Rule = QualifiedName + "=" + Expr
                       | QualifiedName + "++"
                       | QualifiedName + "--"
                       | QualifiedName + ":=" + Expr
                       | QualifiedName + "+=" + Expr
                       | QualifiedName + "-=" + Expr;

              //TODO: MetaFeatures;
              // <[    ] + > because of conflict a[1]>2
              MetaExpr.Rule = LMb + Elements + RMb;

              GlobalList.Rule = "global" + LCb + ParameterList + RCb;

              FuncDefExpr.Rule = "function" + LCb + ParameterList + RCb
            + GlobalList.Q()
            + FuncContract.Q()
            + BlockStatement;

              Expr.Rule =   ConstExpr
                  | BinExpr
                  | UnaryExpr
                  | QualifiedName
                  | AssignExpr
                  | NewStmt
                  | FuncDefExpr
                  | NewArrStmt
                  | ArrayConstructor
                  | MObjectConstructor
                  | TypeConvertExpr
                  | MetaExpr
                  ;

              NewStmt.Rule = "new" + TypeConstructor;
              NewArrStmt.Rule = "new" + TypeExpr + ArrayResolution;
              BinOp.Rule = Symbol("+") | "-" | "*" | "/" | "%" | "^" | "&" | "|"
                  | "&&" | "||" | "==" | "!=" | greater | less
                  | ">=" | "<=";

              LUnOp.Rule = Symbol("~") | "-" | "!" | "$";

              ArrayConstructor.Rule = LSb + ExprList + RSb;

              MObjectPart.Rule = v + arrow + Expr;
              MObjectParts.Rule = MakePlusRule(MObjectParts, comma, MObjectPart);
              MObjectConstructor.Rule = LSb + MObjectParts + RSb;

              OptionalExpression.Rule = Expr.Q();
              #endregion

              #region 3.2 QualifiedName
              TypeExpr.Rule = //MakePlusRule(TypeExpr, dot, v);
              v + GenericsPostfix.Q()
              | TypeExpr + dot + (v + GenericsPostfix.Q());

              GenericsPostfix.Rule = LGb + TypeList + RGb;
              FunctionCall.Rule = LCb + ExprList.Q() + RCb;
              ArrayResolution.Rule = LSb + ExprList + RSb;

              QualifiedName.Rule = v + (GenericsPostfix | ArrayResolution | FunctionCall).Star()
                          | QualifiedName + dot + v + (GenericsPostfix | ArrayResolution | FunctionCall).Star();

              ExprList.Rule = MakePlusRule(ExprList, comma, Expr);
              TypeList.Rule = MakePlusRule(TypeList, comma, TypeExpr);
              TypeConstructor.Rule = TypeExpr + FunctionCall;
              #endregion

              #region 3.3 Statement
              Condition.Rule = LCb + Expr + RCb;
              IfStatement.Rule = "if" + Condition + Statement + ("else" + Statement).Q();
              WhileStatement.Rule = "while" + Condition + Statement;
              ForStatement.Rule = "for" + LCb + OptionalExpression + semicolon + OptionalExpression + semicolon + OptionalExpression + RCb + Statement;
              ForEachStatement.Rule = "foreach" + LCb + v + "in" + Expr + RCb + Statement;
              UsingStatement.Rule = "using" + LCb + Expr + RCb + BlockStatement;
              TryCatchFinallyStatement.Rule = "try" + BlockStatement + "catch" + LCb + v + RCb + BlockStatement + "finally" + BlockStatement;
              SwitchStatement.Rule = "switch" + LCb + Expr + RCb + LFb + SwitchStatements + RFb;
              ExprStatement.Rule = Expr + semicolon;
              FlowControlStatement.Rule = "break" + semicolon
                                | "continue" + semicolon
                                | "return" + Expr + semicolon
                                | "throw" + Expr + semicolon;

              Statement.Rule = semicolon
                      | IfStatement                 //1. If
                      | WhileStatement              //2. While
                      | ForStatement                //3. For
                      | ForEachStatement            //4. ForEach
                      | UsingStatement              //5. Using
                      | SwitchStatement             //6. Switch
                      | BlockStatement              //7. Block
                      | TryCatchFinallyStatement    //8. TryCatch
                      | ExprStatement               //9. Expr
                      | FlowControlStatement;       //10. FlowControl

              Statements.SetOption(TermOptions.IsList);
              Statements.Rule = Statements + Statement | Empty;
              BlockStatement.Rule = LFb + Statements + RFb;

              SwitchStatements.Rule = SwitchCaseStatement.Star() + SwitchDefaultStatement.Q();
              SwitchCaseStatement.Rule = Symbol("case") + Expr + colon + Statements;
              SwitchDefaultStatement.Rule = "default" + colon + Statements;
              #endregion

              #region 3.4 Prog
              FuncContract.Rule = LSb +
                           FuncContractPre + semicolon +
                           FuncContractPost + semicolon +
                           FuncContractInv + semicolon +
                          RSb;
              FuncContractPre.Rule = "pre" + LCb + ExprList.Q() + RCb;
              FuncContractPost.Rule = "post" + LCb + ExprList.Q() + RCb;
              FuncContractInv.Rule = "invariant" + LCb + ExprList.Q() + RCb;

              ParameterList.Rule = MakeStarRule(ParameterList, comma, v);
              FuncDef.Rule = "function" + v + LCb + ParameterList + RCb
            + GlobalList.Q()
            + FuncContract.Q()
            + BlockStatement;

              Element.Rule = Statement | FuncDef;
              Elements.SetOption(TermOptions.IsList);
              Elements.Rule = Elements + Element | Empty;

              Prog.Rule = Elements + Eof;

              Terminal Comment = new CommentTerminal("Comment", "/*", "*/");
              NonGrammarTerminals.Add(Comment);
              Terminal LineComment = new CommentTerminal("LineComment", "//", "\n");
              NonGrammarTerminals.Add(LineComment);

              #endregion
              #endregion

              #region 4. Set starting symbol
              if (!expressionGrammar)
            Root = Prog; // Set grammar root
              else
            Root = Expr;
              #endregion

              #region 5. Operators precedence
              RegisterOperators(1, "=", "+=", "-=", ":=");
              RegisterOperators(2, "|", "||");
              RegisterOperators(3, "&", "&&");
              RegisterOperators(4, "==", "!=", ">", "<", ">=", "<=");
              RegisterOperators(5, "is");
              RegisterOperators(6, "+", "-");
              RegisterOperators(7, "*", "/", "%");
              RegisterOperators(8, Associativity.Right, "^");
              RegisterOperators(9, "~", "!", "$", "++", "--");
              RegisterOperators(10, ".");

              //RegisterOperators(10, Associativity.Right, ".",",", ")", "(", "]", "[", "{", "}");
              //RegisterOperators(11, Associativity.Right, "else");
              #endregion

              #region 6. Punctuation symbols
              RegisterPunctuation( "(", ")", "[", "]", "{", "}", ",", ";" );
              #endregion
        }
Beispiel #2
0
        public BasicGrammar()
        {
            #region Initialisation

            // BASIC is not case sensitive...
            this.CaseSensitive = false;

            // By default, new-line characters are ignored.  Because BASIC uses
            // line breaks to delimit lines, we need to know where the line breaks
            // are.  The following line is required for this.
            this.TokenFilters.Add(new CodeOutlineFilter(false));

            // Define the Terminals
            Terminal number = new NumberLiteral("NUMBER");
            VariableIdentifierTerminal variable = new VariableIdentifierTerminal();
            Terminal stringLiteral = new StringLiteral("STRING", "\"", ScanFlags.None);
            //Important: do not add comment term to base.NonGrammarTerminals list - we do use this terminal in grammar rules
            Terminal comment = new CommentTerminal("Comment", "REM", "\n");

            Terminal comma = Symbol(",", "comma");

            // Make sure reserved keywords of the BASIC language aren't mistaken
            // for variables. Only the keywords ending with '$' could be mistaken
            // for variables.
            variable.AddKeywords(
                "inkey$", "left$", "right$", "mid$", "chr$",
                "space$", "str$", "string$"
            );

            // Define the non-terminals
            NonTerminal PROGRAM = new NonTerminal("PROGRAM", typeof(ProgramNode));
            NonTerminal LINE = new NonTerminal("LINE", typeof(LineNode));
            NonTerminal STATEMENT_LIST = new NonTerminal("STATEMENT_LIST", typeof(StatementListNode));
            NonTerminal STATEMENT = new NonTerminal("STATEMENT", typeof(StatementNode));
            NonTerminal COMMAND = new NonTerminal("COMMAND", typeof(StatementNode)); //TODO: create command node
            NonTerminal PRINT_STMT = new NonTerminal("PRINT_STMT", typeof(PrintStmtNode));
            NonTerminal INPUT_STMT = new NonTerminal("INPUT_STMT", typeof(InputStmtNode));
            NonTerminal IF_STMT = new NonTerminal("IF_STMT", typeof(IfElseStmtNode)); //TODO: join IfStmtNode and IfElseStmtNode in one
            NonTerminal ELSE_CLAUSE_OPT = new NonTerminal("ELSE_CLAUSE_OPT", typeof(GenericJsBasicNode));
            NonTerminal EXPR = new NonTerminal("EXPRESSION", typeof(ExpressionNode));
            NonTerminal EXPR_LIST = new NonTerminal("EXPRESSION_LIST", typeof(ExprListNode));
            NonTerminal BINARY_OP = new NonTerminal("BINARY_OP", typeof(BinaryOpNode));
            NonTerminal BINARY_EXPR = new NonTerminal("BINARY_EXPR", typeof(GenericJsBasicNode)); //TODO: create Binary_expr node
            NonTerminal BRANCH_STMT = new NonTerminal("BRANCH_STMT", typeof(BranchStmtNode));
            NonTerminal ASSIGN_STMT = new NonTerminal("ASSIGN_STMT", typeof(AssignStmtNode));
            NonTerminal FOR_STMT = new NonTerminal("FOR_STMT", typeof(ForStmtNode));
            NonTerminal STEP_OPT = new NonTerminal("STEP_OPT", typeof(GenericJsBasicNode));  //TODO: create step specifier node
            NonTerminal NEXT_STMT = new NonTerminal("NEXT_STMT", typeof(NextStmtNode));
            NonTerminal LOCATE_STMT = new NonTerminal("LOCATE_STMT", typeof(LocateStmtNode));
            NonTerminal WHILE_STMT = new NonTerminal("WHILE_STMT", typeof(WhileStmtNode));
            NonTerminal WEND_STMT = new NonTerminal("WEND_STMT", typeof(WendStmtNode));
            NonTerminal SWAP_STMT = new NonTerminal("SWAP_STMT", typeof(SwapStmtNode));
            NonTerminal GLOBAL_FUNCTION_EXPR = new NonTerminal("GLOBAL_FUNCTION_EXPR", typeof(GlobalFunctionExpr));
            NonTerminal ARG_LIST = new NonTerminal("ARG_LIST", typeof(GenericJsBasicNode));
            NonTerminal FUNC_NAME = new NonTerminal("FUNC_NAME", typeof(GenericJsBasicNode));
            NonTerminal COMMENT_STMT = new NonTerminal("COMMENT_STMT", typeof(RemStmtNode));
            NonTerminal GLOBAL_VAR_EXPR = new NonTerminal("GLOBAL_VAR_EXPR", typeof(GenericJsBasicNode));

            // Set the PROGRAM to be the root node of BASIC programs.
            // A program is a bunch of lines
            this.Root = PROGRAM;

            #endregion

            #region Grammar declaration

            // A program is a collection of lines
            PROGRAM.Rule = MakePlusRule(PROGRAM, null, LINE);

            // A line can be an empty line, or it's a number followed by a statement list ended by a new-line.
            LINE.Rule = NewLine | number + NewLine | number + STATEMENT_LIST + NewLine;

            // A statement list is 1 or more statements separated by the ':' character
            STATEMENT_LIST.Rule = MakePlusRule(STATEMENT_LIST, Symbol(":"), STATEMENT);

            // A statement can be one of a number of types
            STATEMENT.Rule = EXPR | ASSIGN_STMT | PRINT_STMT | INPUT_STMT | IF_STMT | COMMENT_STMT
                                | BRANCH_STMT | COMMAND | FOR_STMT | NEXT_STMT | LOCATE_STMT | SWAP_STMT
                                | WHILE_STMT | WEND_STMT;
            // The different statements are defined here
            PRINT_STMT.Rule = "print" + EXPR_LIST;
            INPUT_STMT.Rule = "input" + EXPR_LIST + variable;
            IF_STMT.Rule = "if" + EXPR + "then" + STATEMENT_LIST + ELSE_CLAUSE_OPT;
            ELSE_CLAUSE_OPT.Rule = Empty | "else" + STATEMENT_LIST;
            BRANCH_STMT.Rule = "goto" + number | "gosub" + number | "return";
            ASSIGN_STMT.Rule = variable + "=" + EXPR;
            LOCATE_STMT.Rule = "locate" + EXPR + comma + EXPR;
            SWAP_STMT.Rule = "swap" + EXPR + comma + EXPR;
            COMMAND.Rule = Symbol("end") | "cls";
            COMMENT_STMT.Rule = comment;

            // An expression is a number, or a variable, a string, or the result of a binary comparison.
            EXPR.Rule = number | variable | stringLiteral | BINARY_EXPR
                      | GLOBAL_VAR_EXPR | GLOBAL_FUNCTION_EXPR | "(" + EXPR + ")";
            BINARY_EXPR.Rule = EXPR + BINARY_OP + EXPR;

            BINARY_OP.Rule = Symbol("+") | "-" | "*" | "/" | "=" | "<=" | ">=" | "<" | ">" | "<>" | "and" | "or";
            //let's do operator precedence right here
            RegisterOperators(50, "*", "/");
            RegisterOperators(40, "+", "-");
            RegisterOperators(30, "=", "<=", ">=", "<", ">", "<>");
            RegisterOperators(20, "and", "or");

            // Used by print and input to allow a bunch of expressions separated by whitespace,
            // or be empty, for example:
            // print
            // print "Hi"
            // print "Hi " a$
            // All of these match "print" EXPR_LIST
            EXPR_LIST.Rule = MakeStarRule(EXPR_LIST, null, EXPR);

            FOR_STMT.Rule = "for" + ASSIGN_STMT + "to" + EXPR + STEP_OPT;
            STEP_OPT.Rule = Empty | "step" + number;
            NEXT_STMT.Rule = "next" + variable;
            WHILE_STMT.Rule = "while" + EXPR;
            WEND_STMT.Rule = "wend";

            //TODO: check number of arguments for particular function in node constructor
            GLOBAL_FUNCTION_EXPR.Rule = FUNC_NAME + "(" + ARG_LIST + ")";
            FUNC_NAME.Rule = Symbol("len") | "left$" | "mid$" | "right$" | "abs" | "asc" | "chr$" | "csrlin$"
                           | "cvi" | "cvs" | "cvd" | "exp" | "fix" | "log" | "pos" | "sgn" | "sin" | "cos" | "tan"
                           | "instr" | "space$" | "spc" | "sqr" | "str$" | "string$" | "val" | "cint";
            ARG_LIST.Rule = MakePlusRule(ARG_LIST, comma, EXPR);

            GLOBAL_VAR_EXPR.Rule = Symbol("rnd") | "timer" | "inkey$" | "csrlin";

            // By registering these strings as "punctuation", we exclude them from
            // appearing in as nodes in the compiled node tree.
            RegisterPunctuation("(", ")", ",");

            #endregion
        }