private static ReadOnlySpan <char> ParseJsConditionalExpression(this ReadOnlySpan <char> literal, JsToken test, out JsConditionalExpression expression) { literal = literal.Advance(1); literal = literal.ParseJsExpression(out var consequent); literal = literal.AdvancePastWhitespace(); if (!literal.FirstCharEquals(':')) { throw new SyntaxErrorException($"Expected Conditional ':' but was {literal.DebugFirstChar()}"); } literal = literal.Advance(1); literal = literal.ParseJsExpression(out var alternate); expression = new JsConditionalExpression(test, consequent, alternate); return(literal); }
public static ReadOnlySpan <char> ParseJsCallExpression(this ReadOnlySpan <char> literal, out JsCallExpression expression, bool filterExpression = false) { literal = literal.ParseIdentifier(out var token); if (!(token is JsIdentifier identifier)) { throw new SyntaxErrorException($"Expected identifier but instead found {token.DebugToken()}"); } literal = literal.AdvancePastWhitespace(); if (literal.FirstCharEquals(WhitespaceArgument)) { literal = literal.Advance(1); literal = literal.ParseWhitespaceArgument(out var argument); expression = new JsCallExpression(identifier, argument); return(literal); } if (literal.StartsWith("=>")) { literal = literal.ParseArrowExpressionBody(new[] { new JsIdentifier("it") }, out var arrowExpr); expression = new JsCallExpression(identifier, arrowExpr); return(literal); } if (!literal.FirstCharEquals('(')) { expression = new JsCallExpression(identifier); return(literal); } literal = literal.Advance(1); literal = literal.ParseArguments(out var args, termination: ')'); expression = new JsCallExpression(identifier, args.ToArray()); return(literal); }
internal static ReadOnlySpan <char> ParseArguments(this ReadOnlySpan <char> literal, out List <JsToken> arguments, char termination) { arguments = new List <JsToken>(); while (!literal.IsNullOrEmpty()) { JsToken listValue; literal = literal.AdvancePastWhitespace(); if (literal[0] == termination) { literal = literal.Advance(1); break; } if (literal.StartsWith("...")) { literal = literal.Advance(3); literal = literal.ParseJsExpression(out listValue); if (!(listValue is JsIdentifier) && !(listValue is JsArrayExpression)) { throw new SyntaxErrorException($"Spread operator expected array but instead found {listValue.DebugToken()}"); } listValue = new JsSpreadElement(listValue); } else { literal = literal.ParseJsExpression(out listValue); } arguments.Add(listValue); literal = literal.AdvancePastWhitespace(); if (literal.IsNullOrEmpty()) { break; } if (literal[0] == termination) { literal = literal.Advance(1); break; } literal = literal.AdvancePastWhitespace(); var c = literal.SafeGetChar(0); if (c.IsEnd() || c == termination) { literal = literal.Advance(1); break; } if (c != ',') { throw new SyntaxErrorException($"Unterminated arguments expression near: {literal.DebugLiteral()}"); } literal = literal.Advance(1); literal = literal.AdvancePastWhitespace(); } literal = literal.AdvancePastWhitespace(); return(literal); }
public static ReadOnlySpan <char> AdvancePastPipeOperator(this ReadOnlySpan <char> literal) => literal.SafeCharEquals(1, '>') ? literal.Advance(2) // support new JS |> operator : ScriptConfig.AllowUnixPipeSyntax ? literal.Advance(1) : throw new SyntaxErrorException("Unix Pipe syntax is disallowed, use JS Pipeline Operator syntax '|>' or set ScriptConfig.AllowUnixPipeSyntax=true; ");