public skipInfo skipChain(List <Token> Tokens, int startingPoint) { int start = startingPoint; int index = startingPoint; int end = 0; Token token = Tokens[index]; if (!token.IsValuable()) { return(new skipInfo { start = start, end = end, delta = 0 }); } while (true) { //Console.WriteLine(token); if (token.Value == "(") { skipInfo skip = engine.expressionParser.SkipFromTo("(", ")", Tokens, index); index = skip.end + 1; } else if (token.Value == "[") { skipInfo skip = engine.expressionParser.SkipFromTo("[", "]", Tokens, index); index = skip.end + 1; } else if (token.Value == "." || token.IsValuable()) { skipInfo skip = engine.expressionParser.SkipAccess(Tokens, index); index = skip.end; } else { break; } if (index == Tokens.Count) { break; } token = Tokens[index]; } end = index; int delta = index - start; return(new skipInfo { start = start, end = end, delta = delta }); }
List <Token> GetSurroundedTokens(string open, string close, int start, List <Token> Tokens) { int index = start; int i = index + 1; skipInfo skip = engine.expressionParser.SkipFromTo(open, close, Tokens, index); int end = skip.end; index = skip.end; return(Tokens.GetRange(i, end - i)); }
/// <summary> /// Parses a list of tokens into an expression recursively /// </summary> public Node ParseExpression(Node branch, List <Token> Tokens) { if (Tokens.Count == 1) { // return resulting end node return(new Node { Body = Tokens[0].Value, //Value = null, TokenType = "" + Tokens[0].Type, Token = Tokens[0], }); } // Create left and right token buffers List <Token> leftBuffer = new List <Token>(); List <Token> rightBuffer = new List <Token>(); bool isInPars = false; bool isMethodCall = false; bool isIndexing = false; bool isArrayLiteral = false; bool isFunctionLiteral = false; bool isChain = false; int accessEnd = 0; // Do logic in delegate so we can easily exit out of it when we need to Action loop = () => { foreach (OperatorGroup OP in OperatorPrecedence) { foreach (Operator Operator in OP.Operators) { int i = 0; bool CanLoop = Tokens.Count > 0; while (CanLoop) { skipInfo s = skipChain(Tokens, i); if (s.delta > 0) { i = s.end - 1; if (s.start == 0 && i == Tokens.Count - 1 && s.delta != 0) { isChain = true; return; } } Token token = Tokens[i]; Token previousToken = i >= 1 ? Tokens[i - 1] : null; if (token.Value == "func") { skipInfo skip = engine.expectValue("(", Tokens, i); i += skip.delta; int start = i; skip = engine.expressionParser.SkipFromTo("(", ")", Tokens, i); i += skip.delta; skip = engine.expressionParser.SkipFromTo("{", "}", Tokens, i); i += skip.delta; if (start == 1 && skip.end == Tokens.Count - 1) { isFunctionLiteral = true; return; } } if (GeneralParser.Keywords.Contains(Tokens[i].Value)) { engine.throwError("Unexpected keyword '" + Tokens[i].Value + "' found", Tokens[i], 2); } //if (token.Value == "(") { // if (previousToken != null) { // // Previous token was identifier; possible method call // if (previousToken.Type == TokenTypes.Identifier) { // skipInfo skip = engine.expressionParser.SkipFromTo("(", ")", Tokens, i); // i += skip.delta; // if (skip.start == 1 && skip.end == Tokens.Count - 1) { // isMethodCall = true; // return; // } // } // } //} if (token.Value == "(") { skipInfo skip = engine.expressionParser.SkipFromTo("(", ")", Tokens, i); i += skip.delta; if (skip.start == 0 && skip.end == Tokens.Count - 1) { isInPars = true; return; } } //if (token.Value == "[") { // if (previousToken != null) { // // Previous token was identifier or string; possible indexing // if (previousToken.Type == TokenTypes.Identifier || previousToken.Type == TokenTypes.StringLiteral) { // skipInfo skip = engine.expressionParser.SkipFromTo("[", "]", Tokens, i); // i += skip.delta; // if (skip.start == 1 && skip.end == Tokens.Count - 1) { // isIndexing = true; // return; // } // } // } //} if (token.Value == "[") { skipInfo skip = engine.expressionParser.SkipFromTo("[", "]", Tokens, i); i += skip.delta; if (skip.start == 0 && skip.end == Tokens.Count - 1) { isArrayLiteral = true; return; } } if (token.Value == Operator.Operation) { // Fill left and right buffers leftBuffer = Tokens.GetRange(0, i); rightBuffer = Tokens.GetRange(i + 1, Tokens.Count - i - 1); bool HasRequiredLeftTokens = leftBuffer.Count > 0; bool HasRequiredRightTokens = rightBuffer.Count > 0; if (OP.Members == 1) { if (OP.IsPostfix) { HasRequiredRightTokens = true; } else { HasRequiredLeftTokens = true; } } if (HasRequiredLeftTokens && HasRequiredRightTokens) { // Create operation node with type and body Node NewNode = new Node(); NewNode.Body = Operator.OperationName; NewNode.TokenType = "" + token.Type; NewNode.Token = token; if (OP.Members == 1) { // Parse unary and do postfix logic Node LeftNode = !OP.IsPostfix ? null : ParseExpression(NewNode, leftBuffer); NewNode.Add(LeftNode); Node RightNode = OP.IsPostfix ? null : ParseExpression(NewNode, rightBuffer); NewNode.Add(RightNode); } else { // Parse operators that need 2 sides Node LeftNode = ParseExpression(NewNode, leftBuffer); NewNode.Add(LeftNode); Node RightNode = ParseExpression(NewNode, rightBuffer); NewNode.Add(RightNode); } branch.Add(NewNode); return; } else { engine.throwError("Missing member of operation!", token, 10); } } // Check if we're still in bounds CanLoop = OP.LeftAssociate ? i < Tokens.Count - 1 : ((Tokens.Count - 1) - i) > 0; i++; } } } }; loop(); if (isChain) { return(ParseChain(Tokens)); } // Parse expression within parenthesis if it's completely surrounded if (isInPars) { return(ParseExpression(branch, Tokens.GetRange(1, Tokens.Count - 2))); } // Parse method call if (isMethodCall) { ParseResult result = ParseCall(Tokens, accessEnd); return(result.node); } // Parse indexing if (isIndexing) { ParseResult result = ParseIndexing(Tokens); return(result.node); } // Parse indexing if (isArrayLiteral) { ParseResult result = ParseArrayLiteral(Tokens); return(result.node); } // Parse function literal if (isFunctionLiteral) { ParseResult result = engine.methodParser.ParseFunctionLiteral(Tokens.GetRange(1, Tokens.Count - 1)); return(result.node); } return(null); }
public Node ParseChain(List <Token> Tokens) { Node node = new Node(); if (Tokens.Count == 2) { engine.throwError("Access operator can only be used after a value!", Tokens[0]); } if (Tokens.Count == 1) { return(ParseExpression(node, Tokens)); } List <Token> Reverse = Tokens.GetRange(0, Tokens.Count); Reverse.Reverse(); if (Reverse[0].Value == "]") { skipInfo skip = SkipFromTo("]", "[", Reverse, 0); if (skip.end + 1 >= Reverse.Count) { engine.throwError("Indexing operator needs left hand value!", Reverse[skip.end]); } else if (Reverse[skip.end + 1].Value == ".") { engine.throwError("Indexing operator needs left hand value!", Reverse[skip.end]); } Node getterNode = new Node(); getterNode.Add(ParseChain(Tokens.GetRange(0, Tokens.Count - (skip.end + 1)))); getterNode.Body = "Getter"; getterNode.TokenType = "Getter"; node.Add(getterNode); //List<Token> ExpressionTokens = Reverse.GetRange(1, skip.end - 1); //ExpressionTokens.Reverse(); //node.Add(ParseExpression(node, ExpressionTokens)); List <Token> ArgumentTokens = Reverse.GetRange(0, skip.end + 1); ArgumentTokens.Reverse(); ParseResult result = engine.generalParser.parseSurroundedExpressions("[", "]", 0, ArgumentTokens); Node argumentsNode = result.node; argumentsNode.Body = "Arguments"; argumentsNode.TokenType = "Arguments"; node.Add(argumentsNode); node.Body = "Index"; node.TokenType = "Index"; } else if (Reverse[0].Value == ")") { skipInfo skip = SkipFromTo(")", "(", Reverse, 0); if (skip.end + 1 >= Reverse.Count) { engine.throwError("Call operator needs left hand value!", Reverse[skip.end]); } else if (Reverse[skip.end + 1].Value == ".") { engine.throwError("Call operator needs left hand value!", Reverse[skip.end]); } Node getterNode = new Node(); getterNode.Add(ParseChain(Tokens.GetRange(0, Tokens.Count - (skip.end + 1)))); getterNode.Body = "Getter"; getterNode.TokenType = "Getter"; node.Add(getterNode); List <Token> ArgumentTokens = Reverse.GetRange(0, skip.end + 1); ArgumentTokens.Reverse(); ParseResult result = engine.generalParser.parseSurroundedExpressions("(", ")", 0, ArgumentTokens); Node argumentsNode = result.node; argumentsNode.Body = "Arguments"; argumentsNode.TokenType = "Arguments"; node.Add(argumentsNode); node.Body = "Call"; node.TokenType = "Call"; } else { node.Body = "access"; node.TokenType = "" + TokenTypes.Punctuator; node.Add(ParseExpression(node, new List <Token> { Reverse[0] })); node.Add(ParseChain(Tokens.GetRange(0, Tokens.Count - 2))); } return(node); }