private ScriptConditionStatement ParseElseStatement(bool isElseIf) { // Case of elsif if (_isLiquid && isElseIf) { return(ParseIfStatement(false, ScriptKeyword.Else())); } // unit test: 200-if-else-statement.txt var nextToken = PeekToken(); if (!_isLiquid && nextToken.Type == TokenType.Identifier && GetAsText(nextToken) == "if") { var elseKeyword = ScriptKeyword.Else(); ExpectAndParseKeywordTo(elseKeyword); return(ParseIfStatement(false, elseKeyword)); } var elseStatement = Open <ScriptElseStatement>(); ExpectAndParseKeywordTo(elseStatement.ElseKeyword); // Parse else statement // unit test: 201-if-else-error4.txt if (ExpectEndOfStatement()) { elseStatement.Body = ParseBlockStatement(elseStatement); } return(Close(elseStatement)); }
private ScriptIfStatement ParseIfStatement(bool invert, ScriptKeyword elseKeyword = null) { // unit test: 200-if-else-statement.txt var ifStatement = Open <ScriptIfStatement>(); ifStatement.ElseKeyword = elseKeyword; if (_isLiquid && elseKeyword != null) { // Parse elseif Open(ifStatement.IfKeyword); NextToken(); Close(ifStatement.IfKeyword); } else { if (_isLiquid && invert) // we have an unless { Open(ifStatement.IfKeyword); // still transfer trivias to IfKeyword NextToken(); Close(ifStatement.IfKeyword); } else { ExpectAndParseKeywordTo(ifStatement.IfKeyword); // Parse if keyword } } var condition = ExpectAndParseExpression(ifStatement, allowAssignment: false); // Transform a `if condition` to `if !(condition)` if (invert) { var invertCondition = ScriptUnaryExpression.Wrap(ScriptUnaryOperator.Not, ScriptToken.Exclamation(), ScriptNestedExpression.Wrap(condition, _isKeepTrivia), _isKeepTrivia); condition = invertCondition; } ifStatement.Condition = condition; if (ExpectEndOfStatement()) { ifStatement.Then = ParseBlockStatement(ifStatement); } return(Close(ifStatement)); }
public ScriptEndStatement() { EndKeyword = ScriptKeyword.End(); CanSkipEvaluation = true; }
public ScriptBreakStatement() { BreakKeyword = ScriptKeyword.Break(); }
private ScriptFunction ParseFunctionStatement(bool isAnonymous) { var scriptFunction = Open <ScriptFunction>(); var previousExpressionLevel = _expressionLevel; try { // Reset expression level when parsing _expressionLevel = 0; if (isAnonymous) { scriptFunction.NameOrDoToken = ExpectAndParseKeywordTo(ScriptKeyword.Do()); } else { scriptFunction.FuncToken = ExpectAndParseKeywordTo(ScriptKeyword.Func()); scriptFunction.NameOrDoToken = ExpectAndParseVariable(scriptFunction); } // If we have parenthesis, this is a function with explicit parameters if (Current.Type == TokenType.OpenParen) { scriptFunction.OpenParen = ParseToken(TokenType.OpenParen); var parameters = new ScriptList <ScriptParameter>(); bool hasTripleDot = false; bool hasOptionals = false; bool isFirst = true; while (true) { // Parse any required comma (before each new non-first argument) // Or closing parent (and we exit the loop) if (Current.Type == TokenType.CloseParen) { scriptFunction.CloseParen = ParseToken(TokenType.CloseParen); scriptFunction.Span.End = scriptFunction.CloseParen.Span.End; break; } if (!isFirst) { if (Current.Type == TokenType.Comma) { PushTokenToTrivia(); NextToken(); FlushTriviasToLastTerminal(); } else { LogError(Current, "Expecting a comma to separate arguments in a function call."); } } isFirst = false; // Else we expect an expression if (IsStartOfExpression()) { var parameter = Open <ScriptParameter>(); var arg = ExpectAndParseVariable(scriptFunction); if (!(arg is ScriptVariableGlobal)) { LogError(arg.Span, "Expecting only a simple name parameter for a function"); } parameter.Name = arg; if (Current.Type == TokenType.Equal) { if (hasTripleDot) { LogError(arg.Span, "Cannot declare an optional parameter after a variable parameter (`...`)."); } hasOptionals = true; parameter.EqualOrTripleDotToken = ScriptToken.Equal(); ExpectAndParseTokenTo(parameter.EqualOrTripleDotToken, TokenType.Equal); parameter.Span.End = parameter.EqualOrTripleDotToken.Span.End; var defaultValue = ExpectAndParseExpression(parameter); if (defaultValue is ScriptLiteral literal) { parameter.DefaultValue = literal; parameter.Span.End = literal.Span.End; } else { LogError(arg.Span, "Expecting only a literal for an optional parameter value."); } } else if (Current.Type == TokenType.TripleDot) { if (hasTripleDot) { LogError(arg.Span, "Cannot declare multiple variable parameters."); } hasTripleDot = true; hasOptionals = true; parameter.EqualOrTripleDotToken = ScriptToken.TripleDot(); ExpectAndParseTokenTo(parameter.EqualOrTripleDotToken, TokenType.TripleDot); parameter.Span.End = parameter.EqualOrTripleDotToken.Span.End; } else if (hasOptionals) { LogError(arg.Span, "Cannot declare a normal parameter after an optional parameter."); } parameters.Add(parameter); scriptFunction.Span.End = parameter.Span.End; } else { LogError(Current, "Expecting an expression for argument function calls instead of this token."); break; } } if (scriptFunction.CloseParen == null) { LogError(Current, "Expecting a closing parenthesis for a function call."); } // Setup parameters once they have been all parsed scriptFunction.Parameters = parameters; } ExpectEndOfStatement(); // If the function is anonymous we don't expect an EOS after the `end` scriptFunction.Body = ParseBlockStatement(scriptFunction, !isAnonymous); } finally { _expressionLevel = previousExpressionLevel; } return(Close(scriptFunction)); }