public static PNode GetCall(string _TYPE, PNode fName, List <PNode> args) { PNode n = new PNode(); n.TYPE = _TYPE; n.PNodes = args; n.PNodes.Insert(0, fName); return(n); }
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); }
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); }
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))); }
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))); }
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); }
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()); }
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)); }
public Parser(List <LToken> _tokens) { tokens = _tokens; Next(); ParseResult res = Statements(); if (res.error != null) { error = res.error; } else { if (current.type != TokenType.EOF) { error = res.Failure(new InvalidSyntaxError(current.position, "Expected End Of File.")).error; } node = res.node; } }
static RTResult VisitBody(PNode node, Context context) { RTResult res = new RTResult(); LToken Ot; List <PNode> PNodes = new List <PNode>(node.PNodes); foreach (PNode n in PNodes.FindAll(x => x.TYPE == "FuncDef" || x.TYPE == "PublicPrototype" || x.TYPE == "PublicFuncDeff" || x.TYPE == "SUPER" || x.TYPE == "RUN" || x.TYPE == "Prototype" || x.isMakeValid())) { Ot = res.Register(Visit(n, context)); if (res.error != null) { return(res); } if ((Ot.type & (TokenType.BREAK | TokenType.CONTINUE | TokenType.RETURN)) != 0) { return(res.Succes(Ot)); } PNodes.Remove(n); } foreach (PNode n in PNodes) { Ot = res.Register(Visit(n, context)); 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))); }
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)); }
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)); }
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))); }
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)); }
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)); }
static RTResult VisitVarAsign(PNode node, Context context) { RTResult res = new RTResult(); if (Compiler.forbidden.Contains(node.val.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is a predefined, unmutable variable", context))); } if (node.TYPE == "PublicVarMake" || node.TYPE == "PublicPrototype") { if (context.GetFunction() == null) { return(res.Failure(new RuntimeError(node.val.position, "Public variables have to be declared in an object.", context))); } } if (node.TYPE == "VarAsign") { if (context.GetFunction() == null) { if (!context.varlist.ContainsKey(node.val.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is not Defined", context))); } } else if (!context.varlist.ContainsKey(node.val.value.text) && !context.GetFunction().InnerValues.ContainsKey(node.val.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is not Defined", context))); } } else if (node.TYPE == "PublicVarMake") { if (context.GetFunction().InnerValues.ContainsKey(node.val.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is already Defined", context))); } } else if (node.TYPE != "PublicPrototype") { if (context.varlist.ContainsKey(node.val.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is already Defined", context))); } } LToken n = res.Register(Visit(node.right, context)); if (res.error != null) { return(res); } LToken Val = new LToken(TokenType.VALUE, n.value, node.val.position).SetContext(n.value.context); Function f = context.GetFunction(); if (node.TYPE == "PublicVarMake" || node.TYPE == "PublicPrototype") { if (Val.value.type == "FUNC") { Val.value.function.InnerValues.parent = f.InnerValues; } f.InnerValues[node.val.value.text] = Val; } else if (f != null) { if (f.InnerValues.ContainsKey(node.val.value.text)) { if (Val.value.type == "FUNC") { Val.value.function.InnerValues.parent = f.InnerValues; } f.InnerValues[node.val.value.text] = Val; } else { context.varlist[node.val.value.text] = Val; } } else { context.varlist[node.val.value.text] = Val; } return(res.Succes(Val.SetContext(context))); }
public PNode(string _TYPE, LToken _opToken, PNode node) { TYPE = _TYPE; right = node; val = _opToken; }
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))); }
public PNode Register(PNode node) { return(node); }
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"); } }
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))); }
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)); }
public ParseResult Succes(PNode _node) { isInnnerCall = false; node = _node; return(this); }
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"))); }
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()); }
public ParseResult Succes(PNode _node, bool b) { node = _node; return(this); }