public Directive KeyFrameBlock(Parser parser, string name, string identifier, int index) { if (!parser.Tokenizer.Match('{')) { return(null); } NodeList keyFrames = new NodeList(); const string identifierRegEx = "from|to|([0-9]+%)"; while (true) { GatherComments(parser); string keyFrameIdentifier; var keyFrameIdentifier1 = parser.Tokenizer.Match(identifierRegEx); if (!keyFrameIdentifier1) { break; } keyFrameIdentifier = keyFrameIdentifier1.Value; if (parser.Tokenizer.Match(",")) { var keyFrameIdentifier2 = parser.Tokenizer.Match(identifierRegEx); if (!keyFrameIdentifier2) { throw new ParsingException("Comma in @keyframe followed by unknown identifier", parser.Tokenizer.Location.Index); } keyFrameIdentifier += "," + keyFrameIdentifier2; } var preComments = GatherAndPullComments(parser); var block = Block(parser); if (block == null) { throw new ParsingException("Expected css block after key frame identifier", parser.Tokenizer.Location.Index); } block.PreComments = preComments; block.PostComments = GatherAndPullComments(parser); keyFrames.Add(NodeProvider.KeyFrame(keyFrameIdentifier, block, parser.Tokenizer.Location.Index)); } if (!parser.Tokenizer.Match('}')) { throw new ParsingException("Expected start, finish, % or '}'", parser.Tokenizer.Location.Index); } return(NodeProvider.Directive(name, identifier, keyFrames, index)); }