public static StyleDeclaration ParseStyleDeclaration(ITokenStream tokens, bool nested) { var selector = ParseOrSelector(tokens, nested); var current = tokens.DrainConsume(); if (!(current is LCurlyToken)) { throw new FormatException($"Unexpected symbol at {tokens.FormatPosition(current)}, '{{' expected."); } var statements = new List <StylesheetStatement>(); while (true) { current = tokens.DrainPeek(); if (current is RCurlyToken) { tokens.DrainConsume(); break; } statements.Add(ParseStatement(tokens)); } return(new StyleDeclaration(selector, statements)); }
public static ScriptDeclaration ParseScriptDeclaration(ITokenStream tokens) { var token = tokens.DrainConsume(); if (!(token is ScriptToken scriptToken)) { throw new FormatException($"Expected script at {tokens.FormatPosition(token)}."); } return(new ScriptDeclaration(scriptToken.Value)); }
public static StylesheetStatement ParseStatement(ITokenStream tokens) { var zero = tokens.DrainPeek(); if (zero is ScriptToken scriptToken) { return(ParseScriptDeclaration(tokens)); } var one = tokens.PeekOnly(t => !(t is WhitespaceToken), 1); if (one is ColonToken) { tokens.Consume(); tokens.DrainConsume(); string key; switch (zero) { case IdentifierToken id: key = id.Value; break; case StringToken str: key = str.Value; break; default: throw new FormatException($"Expected an identifier or string at {tokens.FormatPosition(zero)}."); } var stringBuilder = new StringBuilder(); var ws = false; var counter = 0; foreach (var t in tokens .ConsumeUntil(t => t is SemiColonToken)) { switch (t) { case IdentifierToken id: stringBuilder.Append(id.Value); counter++; ws = false; continue; case StringToken str: stringBuilder.Append(str.Value); counter++; ws = false; continue; case WhitespaceToken _: if (counter > 0 && !ws) { stringBuilder.Append(" "); } ws = true; continue; default: throw new FormatException($"Invalid value at {tokens.FormatPosition(t)}."); } } if (counter == 0) { throw new FormatException($"Expected an assigned value to {tokens.FormatPosition(zero)}."); } tokens.Consume(); if (ws) { stringBuilder.Remove(stringBuilder.Length - 1, 1); } return(new AssignmentStatement(key, stringBuilder.ToString())); } return(ParseStyleDeclaration(tokens, true)); }