public static IList<Expression> ParseArguments(TokensQueue tokens) { var res = new List<Expression>(); while (!tokens.Empty) { var preview = tokens.Peek(); if (preview.Type == TokenType.CloseParenthesis) return res; var arg = Parse(tokens); res.Add(arg); preview = tokens.Peek(); if (preview.Type != TokenType.Comma) break; tokens.Read(TokenType.Comma); } return res; }
protected static Expression ParseLiteral(ref Token token, TokensQueue queue) { if (!queue.Empty) { var preview = queue.Peek(); if (preview.Type == TokenType.OpenParenthesis) { return Func(token, queue); } } return new LiteralExpression(token.StringValue); }
protected static SelectorExpression ParsePseudoSelector(Token token, TokensQueue queue) { var next = queue.Read(TokenType.Literal); if (next.StringValue == "not") { var preview = queue.Peek(); if (preview.Type == TokenType.OpenParenthesis) { queue.Read(TokenType.OpenParenthesis); var expr = Parse(queue); if (!(expr is SimpleSelector)) throw new TokenException("simple selector expected", preview); queue.Read(TokenType.CloseParenthesis); return new NotExpression((SimpleSelector)expr); } } return new PseudoClassSelector(next.StringValue); }
private static Expression ParseWithPriority(TokensQueue tokens, int priority) { var left = ParseOperand(tokens); Token? whiteToken = null; while (!tokens.Empty) { tokens.SkipComments(); var preview = tokens.Peek(); switch (preview.Type) { case TokenType.Semicolon: case TokenType.CloseParenthesis: case TokenType.ExclamationPoint: return left; } var tokenPriority = GetPriority(preview.Type); if (tokenPriority < priority) { return left; } switch (preview.Type) { case TokenType.Plus: case TokenType.Minus: case TokenType.Multiply: case TokenType.Divide: case TokenType.Percentage: case TokenType.LeftShift: case TokenType.RightShift: case TokenType.Comma: var token = tokens.Read(); left = ProcessBinaryExpression(token, left, tokens); whiteToken = null; break; case TokenType.Whitespace: whiteToken = tokens.Read(); break; default: if (whiteToken.HasValue) { left = ProcessBinaryExpression(whiteToken.Value, left, tokens); whiteToken = null; break; } throw new TokenException("unexpected token " + preview.StringValue, preview); } } return left; }
private static Expression ParseNumber(ref Token token, TokensQueue queue) { var inner = new NumberExpression(token.NumberValue); if (!queue.Empty) { var preview = queue.Peek(); if (preview.Type == TokenType.Literal || preview.Type == TokenType.Percentage) { var unitToken = queue.Read(); var unit = ParseUnit(ref unitToken); return new UnitExpression(inner, unit); } } return inner; }
private static CombinatorType ReadCombinatorType(TokensQueue queue) { var hasWhite = false; while (!queue.Empty) { queue.SkipComments(); var preview = queue.Peek(); switch (preview.Type) { case TokenType.Whitespace: queue.Read(); hasWhite = true; break; case TokenType.Plus: queue.Read(); return CombinatorType.Sibling; case TokenType.Greater: queue.Read(); return CombinatorType.Child; case TokenType.Comma: queue.Read(); return CombinatorType.Group; case TokenType.OpenCurlyBracket: case TokenType.CloseParenthesis: return CombinatorType.Stop; default: return hasWhite ? CombinatorType.Descendant : CombinatorType.Combine; } } return CombinatorType.Stop; }
private static SelectorExpression ParseWithPriority(TokensQueue tokens, int priority, SelectorExpression parent = null) { var left = ParseOperand(tokens, parent); while (!tokens.Empty) { tokens.SkipComments(); var preview = tokens.Peek(); switch (preview.Type) { case TokenType.CloseParenthesis: case TokenType.OpenCurlyBracket: return left; } var combinatorType = PeekCombinatorType(tokens); var tokenPriority = GetPriority(combinatorType); if (tokenPriority < priority) { return left; } combinatorType = ReadCombinatorType(tokens); if (combinatorType == CombinatorType.Stop) return left; left = ProcessBinaryExpression(combinatorType, left, tokens); } return left; }