Beispiel #1
0
        ParseResult Power()
        {
            ParseResult res  = new ParseResult();
            PNode       left = res.Register(monomod());

            if (res.error != null)
            {
                return(res);
            }
            bool b = true;

            while (TokenType.POW == current.type)
            {
                b = false;
                LToken opT = current;
                res.Register(Next());
                PNode r = res.Register(factor());
                if (res.error != null)
                {
                    return(res);
                }
                left = PNode.GetBinOP(left, opT, r);
            }
            if (b)
            {
                return(res.Succes(left, true));
            }
            return(res.Succes(left));
        }
Beispiel #2
0
        ParseResult BinOP(PRes func, TokenType type, PRes rop = null)
        {
            if (rop == null)
            {
                rop = func;
            }

            ParseResult res  = new ParseResult();
            PNode       left = res.Register(func());
            bool        b    = true;

            if (res.error != null)
            {
                return(res);
            }
            while ((type & current.type) != 0 && (current.type & TokenType.EQUAL) == 0)
            {
                b = false;
                LToken opT = current;
                res.Register(Next());
                PNode r = res.Register(rop());
                if (res.error != null)
                {
                    return(res);
                }
                left = PNode.GetBinOP(left, opT, r);
            }
            if (b)
            {
                return(res.Succes(left, true));
            }
            return(res.Succes(left));
        }
Beispiel #3
0
        static RTResult VisitCall(PNode node, Context context)
        {
            RTResult res    = new RTResult();
            LToken   toCall = res.Register(Visit(node.PNodes[0], context));

            if (res.error != null)
            {
                return(res);
            }
            if (toCall.value.function == null)
            {
                return(res.Failure(new RuntimeError(node.PNodes[0].val.position, $"{node.PNodes[0].val.value.text} is not a function.", context)));
            }
            List <LToken> args = new List <LToken>();

            for (int n = 1; n < node.PNodes.Count; n++)
            {
                args.Add(res.Register(Visit(node.PNodes[n], context)));
                if (res.error != null)
                {
                    return(res);
                }
            }
            LToken t = res.Register(toCall.value.function.Execute(args, context, toCall.position));

            if (res.error != null)
            {
                return(res);
            }
            return(res.Succes(t.SetContext(context)));
        }
Beispiel #4
0
        static RTResult VisitSetInner(PNode node, Context context)
        {
            RTResult res    = new RTResult();
            LToken   toCall = res.Register(Visit(node.PNodes[0], context));

            if (res.error != null)
            {
                return(res);
            }
            if (toCall.value.type == "LIST")
            {
                LToken v = res.Register(Visit(node.PNodes[1], context));
                if (res.error != null)
                {
                    return(res);
                }
                if (v.value.type != "INT")
                {
                    return(res.Failure(new RuntimeError(v.position, "Element argument has to be an integer.", context)));
                }
                LToken exp = res.Register(Visit(node.PNodes[2], context));
                if (res.error != null)
                {
                    return(res);
                }
                if (v.value.integer < 0 || v.value.integer >= toCall.value.values.Count)
                {
                    return(res.Failure(new RuntimeError(v.position, $"Element argument has to be between 0 and the length of the list ({toCall.value.values.Count}).", context)));
                }

                toCall.value.values[v.value.integer] = exp.value;
                return(res.Succes(exp.SetContext(context)));
            }
            return(res.Failure(new RuntimeError(toCall.position, "List expected", context)));
        }
Beispiel #5
0
        public static void Prepare()
        {
            foreach (string k in Function.Predefs.Keys)
            {
                globalVar[k] = new LToken(TokenType.VALUE, new Value(new Function(new LToken(TokenType.VALUE, new Value(k).SetContext(root), new TextPosition(0, 0, 0, "CONST", "")), null, null, root)).SetContext(root), new TextPosition(0, 0, 0, "CONST", ""));
            }
            root.varlist = globalVar;
            foreach (string s in globalVar.Keys)
            {
                forbidden.Add(s);
            }
            PredefFunc.Insert(globalVar["File"].value.function, new Dictionary <string, Predef>()
            {
                { "ReadText", PredefFunc.ReadText },
                { "ReadLines", PredefFunc.ReadLines },
                { "WriteText", PredefFunc.WriteText },
                { "WriteLines", PredefFunc.WriteLines },
            });
            PredefFunc.Insert(globalVar["String"].value.function, new Dictionary <string, Predef>()
            {
                { "Concat", PredefFunc.Concat },
            });

            foreach (string s in Function.Special.Keys)
            {
                forbidden.Add(s);
            }
        }
Beispiel #6
0
        public ParseResult Statements()
        {
            ParseResult  res    = new ParseResult();
            List <PNode> PNodes = new List <PNode>();
            LToken       str    = current;

            while (true)
            {
                int   b   = index;
                PNode exp = res.TryRegister(statement());
                if (exp == null)
                {
                    Back(index - b);
                    break;
                }
                if (exp.TYPE != "IF" && exp.TYPE != "WHILE" && exp.TYPE != "FOR" && !(current.type == TokenType.RBRACK && (exp.isFuncDef() || exp.TYPE == "Prototype")))
                {
                    if (current.type != TokenType.NLINE)
                    {
                        return(res.Failure(new InvalidSyntaxError(current.position, "Expected ';'")));
                    }
                    Next();
                }
                if (current.type == TokenType.RBRACK && (exp.isFuncDef() || exp.TYPE == "Prototype"))
                {
                    Next();
                }
                PNodes.Add(exp);
            }
            return(res.Succes(new PNode("Body", PNodes, str)));
        }
Beispiel #7
0
 LToken Next()
 {
     index++;
     if (index < tokens.Count)
     {
         current = tokens[index];
     }
     return(current);
 }
Beispiel #8
0
 LToken Back(int n = 1)
 {
     index -= n;
     if (index >= 0)
     {
         current = tokens[index];
     }
     return(current);
 }
Beispiel #9
0
        public static PNode GetFuncDef(LToken fName, List <LToken> args, PNode _node)
        {
            PNode n = new PNode();

            n.TYPE    = "FuncDef";
            n.val     = fName;
            n.LTokens = args;
            n.right   = _node;
            return(n);
        }
Beispiel #10
0
        public static PNode GetBinOP(PNode _left, LToken _opToken, PNode _right)
        {
            PNode n = new PNode();

            n.TYPE  = "BinOp";
            n.left  = _left;
            n.val   = _opToken;
            n.right = _right;
            return(n);
        }
Beispiel #11
0
        public ParseResult if_expr()
        {
            ParseResult res = new ParseResult();
            LToken      str = current;

            Next();
            if (current.type != TokenType.LPAR)
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected '('")));
            }
            Next();
            PNode test = res.Register(expr());

            if (res.error != null)
            {
                return(res);
            }
            if (current.type != TokenType.RPAR)
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected ')'")));
            }
            Next();
            bool  bracketed = current.type == TokenType.LBRACK;
            PNode body      = res.Register(body_statement());

            if (res.error != null)
            {
                return(res);
            }
            if (bracketed && current.type != TokenType.RBRACK)
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected '}'")));
            }
            if (bracketed)
            {
                Next();
            }
            if (current.type == TokenType.KEYWORD && current.value.text == "else")
            {
                Next();
                PNode Ebody = res.Register(body_statement());
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(new PNode("IF", new List <PNode>()
                {
                    test, body, Ebody
                }, str)));
            }
            return(res.Succes(new PNode("IF", new List <PNode>()
            {
                test, body
            }, str)));
        }
Beispiel #12
0
        static RTResult VisitGetInner(PNode node, Context context)
        {
            RTResult res    = new RTResult();
            LToken   toCall = res.Register(Visit(node.PNodes[0], context));

            if (res.error != null)
            {
                return(res);
            }
            if (toCall.value.type == "LIST")
            {
                LToken v = res.Register(Visit(node.PNodes[1], context));
                if (res.error != null)
                {
                    return(res);
                }
                if (v.value.type != "INT")
                {
                    return(res.Failure(new RuntimeError(v.position, "Element argument has to be an integer.", context)));
                }
                if (v.value.integer < 0)
                {
                    return(res.Failure(new RuntimeError(v.position, "Element argument cannot be less then 0.", context)));
                }
                if (v.value.integer < toCall.value.values.Count && v.value.integer >= 0)
                {
                    return(res.Succes(new LToken(TokenType.VALUE, toCall.value.values[v.value.integer], toCall.position).SetContext(context)));
                }
                return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, toCall.position).SetContext(context)));
            }
            else if (toCall.value.type == "STRING")
            {
                LToken v = res.Register(Visit(node.PNodes[1], context));
                if (res.error != null)
                {
                    return(res);
                }
                if (v.value.type != "INT")
                {
                    return(res.Failure(new RuntimeError(v.position, "Element argument has to be an integer.", context)));
                }
                if (v.value.integer < 0)
                {
                    return(res.Failure(new RuntimeError(v.position, "Element argument cannot be less then 0.", context)));
                }
                if (v.value.integer < toCall.value.text.Length && v.value.integer >= 0)
                {
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(toCall.value.text[v.value.integer].ToString()), toCall.position).SetContext(context)));
                }
                return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, toCall.position).SetContext(context)));
            }
            return(res.Failure(new RuntimeError(toCall.position, "List expected", context)));
        }
Beispiel #13
0
 public Function(LToken _name, PNode node, List <string> args, Context _context)
 {
     if (_name.value == null)
     {
         name = new LToken(TokenType.VALUE, new Value("<anonymous>"), _name.position);
     }
     else
     {
         name = _name;
     }
     body                = node;
     argNames            = args;
     DeffCon             = _context;
     InnerValues["this"] = new LToken(TokenType.VALUE, new Value(this).SetContext(name.value.context), name.position);
 }
Beispiel #14
0
        ParseResult factor()
        {
            ParseResult res = new ParseResult();
            LToken      t   = current;

            if ((t.type & (TokenType.ADD | TokenType.SUB)) != 0)
            {
                res.Register(Next());
                PNode f = res.Register(factor());
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(new PNode("UnarOp", t, f)));
            }
            return(Power());
        }
Beispiel #15
0
        static RTResult VisitUnarOp(PNode node, Context context)
        {
            RTResult res = new RTResult();

            if ((node.val.type & (TokenType.INC | TokenType.DEC)) != 0)
            {
                LToken Out = res.Register(Visit(node.PNodes[0], context));
                if (res.error != null)
                {
                    return(res);
                }
                Out = new LToken(TokenType.VALUE, Out.value, Out.position);
                res.Register(Visit(node.PNodes[1], context));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Out));
            }
            LToken n = res.Register(Visit(node.right, context));

            if (res.error != null)
            {
                return(res);
            }

            if (node.val.type == TokenType.SUB)
            {
                if (n.value.isNumber)
                {
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(-n.value.number), n.position).SetContext(n.value.context)));
                }
            }
            if (node.val.type == TokenType.NOT)
            {
                if (n.value.type == "BOOLEAN")
                {
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(!n.value.boolean), n.position).SetContext(n.value.context)));
                }
                else
                {
                    return(res.Failure(new RuntimeError(n.position, "Expected boolean", context)));
                }
            }
            return(res.Succes(n));
        }
Beispiel #16
0
 public Value SetProperty(string prop, LToken val)
 {
     if (type == "FUNC")
     {
         if (function.InnerValues.ContainsKey(prop))
         {
             if (val.value.type == "FUNC")
             {
                 val.value.function.InnerValues.parent = function.InnerValues;
             }
         }
         return((function.InnerValues[prop] = val).value);
     }
     switch (prop)
     {
     default:
         return(NULL);
     }
 }
Beispiel #17
0
        ParseResult newer()
        {
            ParseResult res = new ParseResult();
            bool        n   = false;
            LToken      t   = current;

            if (t.type == TokenType.KEYWORD && t.value.text == "new")
            {
                n = true;
                res.Register(Next());
            }
            PNode node = res.Register(atom());

            if (res.error != null)
            {
                return(res);
            }
            if (n && res.isInnnerCall)
            {
                return(res.Succes(new PNode("NEW", t, node)));
            }
            return(res.Succes(node));
        }
Beispiel #18
0
        ParseResult comp_expr()
        {
            ParseResult res = new ParseResult();
            LToken      t   = current;

            if (current.type == TokenType.NOT)
            {
                res.Register(Next());
                PNode f = res.Register(comp_expr());
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(new PNode("UnarOp", t, f)));
            }
            return(BinOP(aryth_expr,
                         TokenType.EE |
                         TokenType.NE |
                         TokenType.GT |
                         TokenType.GTE |
                         TokenType.LT |
                         TokenType.LTE));
        }
Beispiel #19
0
        ParseResult list_expr()
        {
            ParseResult res = new ParseResult();
            LToken      str = current;

            res.Register(Next());
            List <PNode> args = new List <PNode>();

            if (current.type == TokenType.RSQBR)
            {
                res.Register(Next());
            }
            else
            {
                args.Add(res.Register(expr()));
                if (res.error != null)
                {
                    return(res.Failure(new InvalidSyntaxError(res.error.position, res.error.message + " or expected ']'")));
                }
                while (current.type == TokenType.COMMA)
                {
                    res.Register(Next());
                    args.Add(res.Register(expr()));
                    if (res.error != null)
                    {
                        return(res);
                    }
                }
                if (current.type != TokenType.RSQBR)
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected ',' or ']'")));
                }
                res.Register(Next());
            }
            return(res.Succes(new PNode("MakeList", args, str)));
        }
Beispiel #20
0
        ParseResult atom()
        {
            ParseResult res = new ParseResult();
            LToken      t   = current;

            if (t.type == TokenType.LPAR)
            {
                res.Register(Next());
                PNode e = res.Register(expr());
                if (res.error != null)
                {
                    return(res);
                }
                if (current.type == TokenType.RPAR)
                {
                    res.Register(Next());
                    res.isInnnerCall = true;
                    return(res.Succes(e, true));
                }
                else
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected ')'")));
                }
            }
            if (current.type == TokenType.LBRACK)
            {
                Next();
                PNode stm = res.Register(Statements());
                if (res.error != null)
                {
                    return(res);
                }
                if (current.type != TokenType.RBRACK)
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected '}'")));
                }
                Next();
                stm.TYPE = "MultExpr";
                return(res.Succes(stm));
            }
            if (t.type == TokenType.LSQBR)
            {
                PNode n = res.Register(list_expr());
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(n));
            }
            if (t.type == TokenType.IDENTIFIER)
            {
                res.Register(Next());
                res.isInnnerCall = true;
                return(res.Succes(new PNode("VarGet", t), true));
            }
            if (t.type == TokenType.VALUE)
            {
                res.Register(Next());
                return(res.Succes(new PNode(t)));
            }
            if (t.type == TokenType.KEYWORD && t.value.text == "function")
            {
                PNode fd = res.Register(Func_Def());
                if (res.error != null)
                {
                    return(res);
                }
                res.isInnnerCall = true;
                return(res.Succes(fd, true));
            }
            return(res.Failure(new InvalidSyntaxError(current.position, "Expected number, identifier, plus, minus or parenthesis")));
        }
Beispiel #21
0
        public ParseResult statement()
        {
            ParseResult res = new ParseResult();
            PNode       exp;

            if (current.type == TokenType.KEYWORD && current.value.text == "run")
            {
                LToken pos = current;
                Next();
                exp = res.Register(expr());
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(new PNode("RUN", pos, exp)));
            }
            if (current.type == TokenType.KEYWORD && current.value.text == "Super")
            {
                LToken pos = current;
                Next();
                if (current.type != TokenType.MOVL)
                {
                    return(res.Failure(new InvalidSyntaxError(pos.position, "Expected '<<'")));
                }
                Next();
                exp = res.Register(expr());
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(new PNode("SUPER", pos, exp)));
            }
            if (current.type == TokenType.KEYWORD && current.value.text == "return")
            {
                LToken pos = current;
                Next();
                int b = index;
                exp = res.TryRegister(expr());
                if (exp == null)
                {
                    Back(index - b);
                    exp = new PNode(new LToken(TokenType.VALUE, Value.NULL, pos.position));
                }
                return(res.Succes(new PNode("RETURN", pos, exp)));
            }
            if (current.type == TokenType.KEYWORD && current.value.text == "continue")
            {
                Next();
                return(res.Succes(new PNode("CONTINUE", current)));
            }
            if (current.type == TokenType.KEYWORD && current.value.text == "break")
            {
                Next();
                return(res.Succes(new PNode("BREAK", current)));
            }
            if (current.type == TokenType.KEYWORD && current.value.text == "while")
            {
                PNode n = res.Register(while_expr());
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(n));
            }
            if (current.type == TokenType.KEYWORD && current.value.text == "if")
            {
                PNode n = res.Register(if_expr());
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(n));
            }
            if (current.type == TokenType.KEYWORD && current.value.text == "for")
            {
                PNode n = res.Register(for_expr());
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(n));
            }
            return(expr());
        }
Beispiel #22
0
        public ParseResult for_expr()
        {
            ParseResult res = new ParseResult();
            LToken      str = current;

            Next();
            if (current.type != TokenType.LPAR)
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected '('")));
            }
            Next();
            PNode sing = res.Register(expr());

            if (res.error != null)
            {
                return(res);
            }
            if (current.type != TokenType.NLINE)
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected ';'")));
            }
            Next();
            PNode test = res.Register(expr());

            if (res.error != null)
            {
                return(res);
            }
            if (current.type != TokenType.NLINE)
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected ';'")));
            }
            Next();
            PNode mult = res.Register(expr());

            if (res.error != null)
            {
                return(res);
            }
            if (current.type != TokenType.RPAR)
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected ')'")));
            }
            Next();
            bool  bracketed = current.type == TokenType.LBRACK;
            PNode body      = res.Register(body_statement());

            if (res.error != null)
            {
                return(res);
            }
            if (bracketed && current.type != TokenType.RBRACK)
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected '}'")));
            }
            if (bracketed)
            {
                Next();
            }
            return(res.Succes(new PNode("FOR", new List <PNode>()
            {
                sing, test, mult, body
            }, str)));
        }
Beispiel #23
0
        static RTResult VisitBinOp(PNode node, Context context)
        {
            RTResult res = new RTResult();
            LToken   r   = res.Register(Visit(node.right, context));

            if (res.error != null)
            {
                return(res);
            }
            LToken l = res.Register(Visit(node.left, context));

            if (res.error != null)
            {
                return(res);
            }

            switch (node.val.type)
            {
            case TokenType.EE:
                return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value == r.value), l.position).SetContext(context)));

            case TokenType.NE:
                return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value != r.value), l.position).SetContext(context)));
            }

            if (l.value.isNumber && r.value.isNumber)
            {
                switch (node.val.type)
                {
                case TokenType.ADD:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number + r.value.number), l.position).SetContext(l.value.context)));

                case TokenType.SUB:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number - r.value.number), l.position).SetContext(l.value.context)));

                case TokenType.MULT:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number * r.value.number), l.position).SetContext(l.value.context)));

                case TokenType.DIV:
                    if (r.value.number == 0)
                    {
                        res.Failure(new RuntimeError(node.val.position, "Division by zero error", context));
                    }

                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number / r.value.number), l.position).SetContext(l.value.context)));

                case TokenType.POW:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(Math.Pow(l.value.number, r.value.number)), l.position).SetContext(l.value.context)));

                case TokenType.MOD:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number % r.value.number), l.position).SetContext(l.value.context)));

                case TokenType.GT:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number > r.value.number), l.position).SetContext(context)));

                case TokenType.LT:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number < r.value.number), l.position).SetContext(context)));

                case TokenType.GTE:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number >= r.value.number), l.position).SetContext(context)));

                case TokenType.LTE:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number <= r.value.number), l.position).SetContext(context)));
                }
            }
            else if (l.value.type == "BOOLEAN" && r.value.type == "BOOLEAN")
            {
                switch (node.val.type)
                {
                case TokenType.AND:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.boolean && r.value.boolean), l.position).SetContext(l.value.context)));

                case TokenType.OR:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.boolean || r.value.boolean), l.position).SetContext(l.value.context)));
                }
            }
            else if (l.value.type == "LIST" && r.value.type == "LIST")
            {
                switch (node.val.type)
                {
                case TokenType.ADD:
                    List <Value> Vs = new List <Value>(l.value.values.ToArray());
                    Vs.AddRange(r.value.values);
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(Vs), l.position).SetContext(l.value.context)));
                }
            }
            else if (l.value.type == "STRING" || r.value.type == "STRING")
            {
                switch (node.val.type)
                {
                case TokenType.ADD:
                    return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.ToString() + r.value.ToString()), l.position).SetContext(l.value.context)));
                }
            }


            return(res.Failure(new RuntimeError(node.val.position, $"Invalid operation for {l.value.type} and {r.value.type}.", context)));
        }
Beispiel #24
0
        ParseResult expr()
        {
            ParseResult res     = new ParseResult();
            bool        publish = false;

            if (current.type == TokenType.KEYWORD && current.value.text == "public")
            {
                res.Register(Next());
                if (current.type == TokenType.KEYWORD && current.value.text == "function")
                {
                    PNode fd = res.Register(Func_Def());
                    if (res.error != null)
                    {
                        return(res);
                    }
                    if (fd.val.value == null)
                    {
                        return(res.Failure(new InvalidSyntaxError(fd.val.position, "Public function can not be anonymous.")));
                    }
                    fd.TYPE = "PublicFuncDeff";
                    return(res.Succes(fd));
                }
                if (current.type == TokenType.KEYWORD && current.value.text == "let")
                {
                    publish = true;
                }
                else
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected let or function")));
                }
            }
            if (current.type == TokenType.KEYWORD && current.value.text == "let")
            {
                res.Register(Next());
                if (current.type != TokenType.IDENTIFIER)
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected an identifier")));
                }

                LToken Vname = current;
                PNode  exp   = new PNode(new LToken(TokenType.VALUE, Value.NULL, current.position));;
                res.Register(Next());
                if (current.type == TokenType.EQUAL)
                {
                    res.Register(Next());
                    exp = res.Register(expr());
                    if (res.error != null)
                    {
                        return(res);
                    }
                }

                if (publish)
                {
                    return(res.Succes(new PNode("PublicVarMake", Vname, exp)));
                }
                return(res.Succes(new PNode("VarMake", Vname, exp)));
            }
            if (publish)
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected let or function.")));
            }

            if (current.type == TokenType.IDENTIFIER)
            {
                LToken Vname = current;
                res.Register(Next());
                if ((current.type & TokenType.EQUAL) != 0)
                {
                    TokenType t = current.type;
                    res.Register(Next());
                    PNode exp = res.Register(expr());
                    if (res.error != null)
                    {
                        return(res);
                    }
                    if ((t & (TokenType.ADD | TokenType.SUB | TokenType.MULT | TokenType.DIV | TokenType.POW)) != 0)
                    {
                        exp = PNode.GetBinOP(new PNode("VarGet", Vname), new LToken(t ^ TokenType.EQUAL), exp);
                    }
                    return(res.Succes(new PNode("VarAsign", Vname, exp)));
                }
                res.Register(Back());
            }


            PNode node = res.Register(BinOP(comp_expr, TokenType.AND | TokenType.OR));

            if (res.error != null)
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected, let, number, identifier, plus, minus or parenthesis")));
            }
            if (current.type == TokenType.MOVL)
            {
                res.Register(Next());
                if (current.type != TokenType.IDENTIFIER)
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected an identifier")));
                }
                LToken Pname = current;
                PNode  exp   = new PNode(new LToken(TokenType.VALUE, Value.NULL, current.position));
                res.Register(Next());
                if (current.type == TokenType.EQUAL)
                {
                    res.Register(Next());
                    exp = res.Register(expr());
                    if (res.error != null)
                    {
                        return(res);
                    }
                }

                return(res.Succes(new PNode("Prototype", new List <PNode>()
                {
                    node, exp
                }, Pname)));
            }
            if (res.isInnnerCall)
            {
                if ((current.type & TokenType.EQUAL) != 0)
                {
                    TokenType t = current.type;
                    res.Register(Next());
                    PNode exp = res.Register(expr());
                    if (res.error != null)
                    {
                        return(res);
                    }
                    if ((t & (TokenType.ADD | TokenType.SUB | TokenType.MULT | TokenType.DIV | TokenType.POW)) != 0)
                    {
                        exp = PNode.GetBinOP(node, new LToken(t ^ TokenType.EQUAL), exp);
                    }
                    if (node.TYPE == "GetInner")
                    {
                        List <PNode> pns = new List <PNode>(node.PNodes);
                        pns.RemoveAt(0);
                        pns.Add(exp);
                        return(res.Succes(PNode.GetCall("InnerAsign", node.PNodes[0], pns)));
                    }
                    return(res.Succes(PNode.GetCall("PropertyAsign", node, new List <PNode>()
                    {
                        exp
                    })));
                }
            }
            return(res.Succes(node));
        }
Beispiel #25
0
        ParseResult Func_Def()
        {
            ParseResult res = new ParseResult();

            if (current.type != TokenType.KEYWORD || current.value.text != "function")
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected function keyword")));
            }
            LToken FName = new LToken(TokenType.VALUE, null, current.position);

            res.Register(Next());
            if (current.type == TokenType.IDENTIFIER)
            {
                FName = new LToken(TokenType.VALUE, new Value(current.value.text), current.position);
                res.Register(Next());
                if (current.type != TokenType.LPAR)
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected '('")));
                }
            }
            else
            {
                if (current.type != TokenType.LPAR)
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected '(' or an identifier")));
                }
            }
            res.Register(Next());
            List <LToken> args = new List <LToken>();

            if (current.type == TokenType.IDENTIFIER)
            {
                args.Add(new LToken(TokenType.VALUE, new Value(current.value.text), current.position));
                res.Register(Next());
                while (current.type == TokenType.COMMA)
                {
                    res.Register(Next());
                    if (current.type != TokenType.IDENTIFIER)
                    {
                        return(res.Failure(new InvalidSyntaxError(current.position, "Expected an identifier")));
                    }
                    args.Add(new LToken(TokenType.VALUE, new Value(current.value.text), current.position));
                    res.Register(Next());
                }
                if (current.type != TokenType.RPAR)
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected ')' or ','")));
                }
            }
            else if (current.type != TokenType.RPAR)
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected ')'")));
            }

            res.Register(Next());
            PNode ret = null;

            if (current.type == TokenType.ARROW)
            {
                res.Register(Next());
                ret = res.Register(expr());
                if (res.error != null)
                {
                    return(res);
                }
            }
            else if (current.type == TokenType.LBRACK)
            {
                Next();
                ret = res.Register(Statements());
                if (res.error != null)
                {
                    return(res);
                }
                if (current.type != TokenType.RBRACK)
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected '}'")));
                }
            }
            else
            {
                return(res.Failure(new InvalidSyntaxError(current.position, "Expected '=>' or '{'")));
            }
            return(res.Succes(PNode.GetFuncDef(FName, args, ret)));
        }
Beispiel #26
0
        static public RTResult Visit(PNode node, Context context)
        {
            RTResult res = new RTResult();
            LToken   Ot;
            Function f;
            Value    v;

            switch (node.TYPE)
            {
            case "VALUE":
                return(res.Succes(node.val.SetContext(context)));

            case "VarAsign":
            case "PublicVarMake":
            case "PublicPrototype":
            case "VarMake":
                Ot = res.Register(VisitVarAsign(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            case "VarGet":
                f = context.GetFunction();
                if (f != null)
                {
                    if (f.InnerValues.ContainsKey(node.val.value.text))
                    {
                        return(res.Succes(f.InnerValues[node.val.value.text]));
                    }
                }
                if (!context.varlist.ContainsKey(node.val.value.text))
                {
                    return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is not defined", context)));
                }
                return(res.Succes(context.varlist[node.val.value.text]));

            case "BinOp":
                Ot = res.Register(VisitBinOp(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            case "UnarOp":
                Ot = res.Register(VisitUnarOp(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            case "PublicFuncDeff":
                f = new Function(node.val, node.right, node.LTokens.ConvertAll(x => x.value.text), context);
                Function CF = context.GetFunction();
                f.InnerValues.parent = CF.InnerValues;
                CF.InnerValues[node.val.value.text] = new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context);;
                return(res.Succes(new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context)));

            case "FuncDef":
                f = new Function(node.val, node.right, node.LTokens.ConvertAll(x => x.value.text), context);
                if (node.val.value != null)
                {
                    context.varlist[node.val.value.text] = new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context);
                }
                return(res.Succes(new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context)));

            case "CallFunc":
                Ot = res.Register(VisitCall(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                Ot.type = TokenType.VALUE;
                return(res.Succes(Ot));

            case "MakeList":
                List <Value> values = new List <Value>();
                foreach (PNode n in node.PNodes)
                {
                    values.Add(res.Register(Visit(n, context)).value);
                    if (res.error != null)
                    {
                        return(res);
                    }
                }
                return(res.Succes(new LToken(TokenType.VALUE, new Value(values), node.val.position).SetContext(context)));

            case "Prototype":
                Ot = res.Register(Visit(node.PNodes[0], context));
                if (res.error != null)
                {
                    return(res);
                }
                if (Ot.value.type != "FUNC")
                {
                    return(res.Failure(new RuntimeError(Ot.position, "Value to prototype into has to be a function.", context)));
                }
                if (Compiler.forbidden.Contains(Ot.value.function.name.value.text))
                {
                    return(res.Failure(new RuntimeError(node.val.position, $"{Ot.value.function.name.value.text} is a predefined, unmutable variable", context)));
                }
                Ot.value.function.body.PNodes.Add(new PNode("PublicPrototype", node.val, node.PNodes[1]));
                return(res.Succes(Ot));

            case "GetProperty":
                Ot = res.Register(Visit(node.right, context));
                if (res.error != null)
                {
                    return(res);
                }
                v  = Ot.value.GetProperty(node.val.value.text);
                Ot = new LToken(TokenType.VALUE, v, Ot.position);
                return(res.Succes(Ot.SetContext(context)));

            case "PropertyAsign":
                Ot = res.Register(Visit(node.PNodes[1], context));
                v  = res.Register(Visit(node.PNodes[0].right, context)).value.SetProperty(node.PNodes[0].val.value.text, Ot);
                Ot = new LToken(TokenType.VALUE, v, Ot.position);
                return(res.Succes(Ot.SetContext(context)));

            case "CallProperty":
                LToken toCall = res.Register(Visit(node.PNodes[0], context));
                if (res.error != null)
                {
                    return(res);
                }
                List <LToken> args = new List <LToken>();
                for (int n = 1; n < node.PNodes.Count; n++)
                {
                    args.Add(res.Register(Visit(node.PNodes[n], context)));
                    if (res.error != null)
                    {
                        return(res);
                    }
                }
                LToken t = res.Register(toCall.value.CallProperty(node.val.value.text, args, context, toCall.position));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(t.SetContext(context)));

            case "GetInner":
                Ot = res.Register(VisitGetInner(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            case "InnerAsign":
                Ot = res.Register(VisitSetInner(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            case "IF":
            {
                Context ctx = BracketContext(context);
                Ot = res.Register(Visit(node.PNodes[0], ctx));
                if (res.error != null)
                {
                    return(res);
                }
                if (Ot.value.boolean)
                {
                    Ot = res.Register(Visit(node.PNodes[1], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                    if ((Ot.type & (TokenType.BREAK | TokenType.CONTINUE | TokenType.RETURN)) != 0)
                    {
                        return(res.Succes(Ot));
                    }
                }
                else if (node.PNodes.Count == 3)
                {
                    Ot = res.Register(Visit(node.PNodes[2], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                    if ((Ot.type & (TokenType.BREAK | TokenType.CONTINUE | TokenType.RETURN)) != 0)
                    {
                        return(res.Succes(Ot));
                    }
                }
            }
                return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position)));

            case "WHILE":
            {
                Context ctx = BracketContext(context);
                Ot = res.Register(Visit(node.PNodes[0], ctx));
                if (res.error != null)
                {
                    return(res);
                }
                while (Ot.value.boolean)
                {
                    Ot = res.Register(Visit(node.PNodes[1], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                    if (Ot.type == TokenType.BREAK)
                    {
                        break;
                    }
                    if (Ot.type == TokenType.RETURN)
                    {
                        return(res.Succes(Ot));
                    }
                    ctx = BracketContext(context);
                    Ot  = res.Register(Visit(node.PNodes[0], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                }
            }
                return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position)));

            case "FOR":
            {
                Context CON = BracketContext(context);
                res.Register(Visit(node.PNodes[0], CON));
                Ot = res.Register(Visit(node.PNodes[1], CON));
                if (res.error != null)
                {
                    return(res);
                }
                Context ctx = BracketContext(CON);
                while (Ot.value.boolean)
                {
                    Ot = res.Register(Visit(node.PNodes[3], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                    if (Ot.type == TokenType.BREAK)
                    {
                        break;
                    }
                    if (Ot.type == TokenType.RETURN)
                    {
                        return(res.Succes(Ot));
                    }
                    ctx = BracketContext(CON);
                    res.Register(Visit(node.PNodes[2], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                    Ot = res.Register(Visit(node.PNodes[1], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                }
                return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position)));
            }

            case "MultExpr":
                return(VisitBody(node, BracketContext(context)));

            case "Body":
                return(VisitBody(node, context));

            case "NEW":
                Ot = res.Register(Visit(node.right, context));
                if (res.error != null)
                {
                    return(res);
                }
                if (Ot.value.type != "FUNC")
                {
                    return(res.Failure(new RuntimeError(node.val.position, "'new' copy can be only aplied to functions.", context)));
                }
                return(res.Succes(Ot.Copy(false)));

            case "RETURN":
                Ot = res.Register(Visit(node.right, context));
                if (res.error != null)
                {
                    return(res);
                }
                Ot.type = TokenType.RETURN;
                return(res.Succes(Ot));

            case "BREAK":
                return(res.Succes(new LToken(TokenType.BREAK, Value.NULL, node.val.position)));

            case "CONTINUE":
                return(res.Succes(new LToken(TokenType.CONTINUE, Value.NULL, node.val.position)));

            case "SUPER":
                f = context.GetFunction();
                if (f == null)
                {
                    return(res.Failure(new RuntimeError(node.val.position, "Super can only be called inside a function.", context)));
                }
                Ot = res.Register(Visit(node.right, context));
                if (res.error != null)
                {
                    return(res);
                }
                if (Ot.value.type != "FUNC")
                {
                    return(res.Failure(new RuntimeError(Ot.position, "Function can only accept another function as a Super.", context)));
                }
                f.InnerValues.Merge(Ot.value.function.InnerValues, f);
                return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position)));

            case "RUN":
                Ot = res.Register(Visit(node.right, context));
                if (res.error != null)
                {
                    return(res);
                }
                if (Ot.value.type != "STRING")
                {
                    return(res.Failure(new RuntimeError(node.val.position, "Run statement requires a string argument.", context)));
                }
                if (!System.IO.File.Exists(Ot.value.text))
                {
                    return(res.Failure(new RuntimeError(Ot.position, $"File {Ot.value.text} does not exist.", context)));
                }
                Ot = res.Register(Compiler.Run(System.IO.File.ReadAllText(Ot.value.text), new System.IO.FileInfo(Ot.value.text).Name));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            default:
                throw new Exception("Visit not defined");
            }
        }
Beispiel #27
0
 public RTResult Succes(LToken _value)
 {
     value = _value;
     return(this);
 }
Beispiel #28
0
 public PNode Register(LToken t)
 {
     advanceC++;
     return(null);
 }
Beispiel #29
0
        ParseResult monomod()
        {
            ParseResult res = new ParseResult();
            PNode       node;

            if (current.type == TokenType.INC || current.type == TokenType.DEC)
            {
                LToken op = current;
                res.Register(Next());
                node = res.Register(call(newer()));
                if (res.error != null)
                {
                    return(res);
                }
                if (op.type == TokenType.INC)
                {
                    op.type = TokenType.ADD;
                }
                else
                {
                    op.type = TokenType.SUB;
                }
                PNode exp = PNode.GetBinOP(node, op, new PNode(new LToken(TokenType.VALUE, new Value(1), op.position)));

                if (node.TYPE == "VarGet")
                {
                    return(res.Succes(new PNode("VarAsign", node.val, exp)));
                }

                if (!res.isInnnerCall)
                {
                    return(res.Failure(new InvalidSyntaxError(op.position, "Increment and decrement operators can only edit immediate variables")));
                }

                List <PNode> pns = new List <PNode>(node.PNodes);
                pns.RemoveAt(0);
                pns.Add(exp);
                return(res.Succes(PNode.GetCall("InnerAsign", node.PNodes[0], pns)));
            }
            node = res.Register(call(newer()));
            if (current.type == TokenType.INC || current.type == TokenType.DEC)
            {
                LToken op = current;
                LToken ed = current.Copy(false);
                if (!res.isInnnerCall && node.TYPE != "VarGet")
                {
                    return(res.Failure(new InvalidSyntaxError(op.position, "Increment and decrement operators can only edit immediate variables")));
                }
                res.Register(Next());

                if (op.type == TokenType.INC)
                {
                    ed.type = TokenType.ADD;
                }
                else
                {
                    ed.type = TokenType.SUB;
                }
                PNode exp = PNode.GetBinOP(node, ed, new PNode(new LToken(TokenType.VALUE, new Value(1), op.position)));

                if (node.TYPE == "VarGet")
                {
                    exp = new PNode("VarAsign", node.val, exp);
                }
                else
                {
                    List <PNode> pns = new List <PNode>(node.PNodes);
                    pns.RemoveAt(0);
                    pns.Add(exp);
                    exp = PNode.GetCall("InnerAsign", node.PNodes[0], pns);
                }
                return(res.Succes(new PNode("UnarOp", new List <PNode>()
                {
                    node, exp
                }, op)));
            }
            return(res.Succes(node, true));
        }
Beispiel #30
0
        ParseResult call(ParseResult toCall)
        {
            ParseResult res = new ParseResult();
            PNode       at  = res.Register(toCall);

            if (res.error != null)
            {
                return(res);
            }

            if (current.type == TokenType.LPAR)
            {
                res.Register(Next());
                List <PNode> args = new List <PNode>();
                if (current.type == TokenType.RPAR)
                {
                    res.Register(Next());
                }
                else
                {
                    args.Add(res.Register(expr()));
                    if (res.error != null)
                    {
                        return(res.Failure(new InvalidSyntaxError(res.error.position, res.error.message + " or expected ')'")));
                    }
                    while (current.type == TokenType.COMMA)
                    {
                        res.Register(Next());
                        args.Add(res.Register(expr()));
                        if (res.error != null)
                        {
                            return(res);
                        }
                    }
                    if (current.type != TokenType.RPAR)
                    {
                        return(res.Failure(new InvalidSyntaxError(current.position, "Expected ',' or ')'")));
                    }
                    res.Register(Next());
                }
                return(call(res.Succes(PNode.GetCall("CallFunc", at, args))));
            }
            else if (current.type == TokenType.LSQBR)
            {
                res.Register(Next());
                if (current.type == TokenType.RSQBR)
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected int")));
                }
                PNode n = res.Register(expr());
                if (current.type != TokenType.RSQBR)
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected ']'")));
                }
                res.Register(Next());
                res.isInnnerCall = true;
                return(call(res.Succes(PNode.GetCall("GetInner", at, new List <PNode>()
                {
                    n
                }), true)));
            }
            else if (current.type == TokenType.DOT)
            {
                res.Register(Next());
                if (current.type != TokenType.IDENTIFIER)
                {
                    return(res.Failure(new InvalidSyntaxError(current.position, "Expected identifier")));
                }
                LToken id = current;
                res.Register(Next());
                if (current.type == TokenType.LPAR)
                {
                    res.Register(Next());
                    List <PNode> args = new List <PNode>();
                    if (current.type == TokenType.RPAR)
                    {
                        res.Register(Next());
                    }
                    else
                    {
                        args.Add(res.Register(expr()));
                        if (res.error != null)
                        {
                            return(res.Failure(new InvalidSyntaxError(res.error.position, res.error.message + " or expected ')'")));
                        }
                        while (current.type == TokenType.COMMA)
                        {
                            res.Register(Next());
                            args.Add(res.Register(expr()));
                            if (res.error != null)
                            {
                                return(res);
                            }
                        }
                        if (current.type != TokenType.RPAR)
                        {
                            return(res.Failure(new InvalidSyntaxError(current.position, "Expected ',' or ')'")));
                        }
                        res.Register(Next());
                    }
                    PNode RET = PNode.GetCall("CallProperty", at, args);
                    RET.val = id;
                    return(call(res.Succes(RET)));
                }
                res.isInnnerCall = true;
                return(call(res.Succes(new PNode("GetProperty", id, at), true)));
            }
            return(res.Succes(at, true));
        }