/// <summary> /// Parses a conditional statement. /// </summary> public ParseResult ParseConditional(List <Token> tokens) { var node = new ConditionalNode(); var scopeCheck = new ScopeCheck(); for (int i = 0; i < tokens.Count; i++) { var token = tokens[i]; scopeCheck.Check(token); if (token.Equals("?", TokenTypes.Punctuator) && scopeCheck.IsInScope) { SkipInfo skip = SkipFromTo("?", ":", tokens, i); var conditionNode = ParseClean(tokens.GetRange(0, i)); var successNode = ParseClean(tokens.GetRange(i + 1, skip.Delta - 1)); var failNode = ParseClean(tokens.GetRange(skip.End + 1, tokens.Count - (skip.End + 1))); node.Condition = conditionNode ?? throw new SkryptException("Syntax error, condition statement can't be empty"); node.Pass = successNode ?? throw new SkryptException("Syntax error, consequent statement can't be empty"); node.Fail = failNode ?? throw new SkryptException("Syntax error, alternative statement can't be empty"); return(new ParseResult { Node = node, Delta = tokens.Count }); } } _engine.ThrowError("Syntax error, conditional statement incomplete", tokens[0]); return(null); }
/// <summary> /// Parses a list of tokens into an expression node /// </summary> public ParseResult Parse(List <Token> tokens) { var node = new Node(); var delta = 0; var addDelta = 0; var deltaOffset = 0; var scopeCheck = new ScopeCheck(); var previousToken = default(Token); if (tokens[0].Type == TokenTypes.EndOfExpression) { delta++; deltaOffset = 1; } // Loop until we hit the end of an expression, or consumed all tokens. while (true) { scopeCheck.Check(tokens[delta]); if (scopeCheck.IsInScope && tokens[delta].Type == TokenTypes.EndOfExpression) { if (tokens[delta].Type == TokenTypes.EndOfExpression) { addDelta = 1; break; } } previousToken = tokens[delta]; delta++; if (delta == tokens.Count) { break; } } var returnNode = ParseClean(tokens.GetRange(deltaOffset, delta - deltaOffset)); returnNode = ExpressionOptimiser.OptimiseExpressionNode(returnNode, _engine); delta += addDelta; return(new ParseResult { Node = returnNode, Delta = delta }); }
/// <summary> /// Parses individual arguments as expressions. /// </summary> public void SetArguments(List <List <Token> > arguments, List <Token> tokens) { var i = 0; var buffer = new List <Token>(); var isFirst = true; var scopeCheck = new ScopeCheck(); for (i = 0; i < tokens.Count; i++) { var token = tokens[i]; buffer.Add(token); scopeCheck.Check(token); // Only set arguments if they're not inside nested function calls. if (scopeCheck.IsInScope) { if (token.Equals(",", TokenTypes.Punctuator)) { isFirst = false; // Arguments cannot be empty. if (buffer.Count == 0) { _engine.ThrowError("Syntax error, missing tokens for argument.", tokens[i]); } buffer.RemoveAt(buffer.Count - 1); arguments.Add(new List <Token>(buffer)); buffer.Clear(); } // Reached the end of all argument tokens. // All tokens from the start, or from the last ',' token are part of the last argument. if (i == tokens.Count - 1) { // Arguments cannot be empty. if (buffer.Count == 0 && !isFirst) { _engine.ThrowError("Syntax error, missing tokens for argument.", tokens[i]); } arguments.Add(new List <Token>(buffer)); buffer.Clear(); } } } }
// Checks whether a list of tokens is a valid conditional statement. private bool IsConditional(List <Token> tokens) { var isConditional = false; var scopeCheck = new ScopeCheck(); for (int i = 0; i < tokens.Count; i++) { var token = tokens[i]; scopeCheck.Check(token); if (token.Equals("?", TokenTypes.Punctuator) && scopeCheck.IsInScope) { isConditional = true; SkipInfo skip = SkipFromTo("?", ":", tokens, i); } } return(isConditional); }