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)); }
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)); }
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))); }
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))); }
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); } }
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))); }
LToken Next() { index++; if (index < tokens.Count) { current = tokens[index]; } return(current); }
LToken Back(int n = 1) { index -= n; if (index >= 0) { current = tokens[index]; } return(current); }
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 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); } }
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 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 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))); }
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 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))); }
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)); }
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))); }
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"); } }
public RTResult Succes(LToken _value) { value = _value; return(this); }
public PNode Register(LToken t) { advanceC++; return(null); }
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)); }