content: // Copyright 2016 Google Inc. Use of this source code is governed by an
  // MIT-style license that can be found in the LICENSE file or at
  // https://opensource.org/licenses/MIT.
  
  import 'package:charcode/charcode.dart';
  
  import '../util/character.dart';
  import 'parser.dart';
  
  /// A parser for `@keyframes` block selectors.
  class KeyframeSelectorParser extends Parser {
    KeyframeSelectorParser(super.contents, {super.url, super.interpolationMap});
  
    List<String> parse() {
      return wrapSpanFormatException(() {
        var selectors = <String>[];
        do {
          _whitespace();
          if (lookingAtIdentifier()) {
            if (scanIdentifier("from")) {
              selectors.add("from");
            } else {
              expectIdentifier("to", name: '"to" or "from"');
              selectors.add("to");
            }
          } else {
            selectors.add(_percentage());
          }
          _whitespace();
        } while (scanner.scanChar($comma));
        scanner.expectDone();
  
        return selectors;
      });
    }
  
    String _percentage() {
      var buffer = StringBuffer();
      if (scanner.scanChar($plus)) buffer.writeCharCode($plus);
  
      var second = scanner.peekChar();
      if (!second.isDigit && second != $dot) {
        scanner.error("Expected number.");
      }
  
      while (scanner.peekChar().isDigit) {
        buffer.writeCharCode(scanner.readChar());
      }
  
      if (scanner.peekChar() == $dot) {
        buffer.writeCharCode(scanner.readChar());
  
        while (scanner.peekChar().isDigit) {
          buffer.writeCharCode(scanner.readChar());
        }
      }
  
      if (scanIdentChar($e)) {
        buffer.writeCharCode($e);
        if (scanner.peekChar() case $plus || $minus) {
          buffer.writeCharCode(scanner.readChar());
        }
        if (!scanner.peekChar().isDigit) scanner.error("Expected digit.");
  
        do {
          buffer.writeCharCode(scanner.readChar());
        } while (scanner.peekChar().isDigit);
      }
  
      scanner.expectChar($percent);
      buffer.writeCharCode($percent);
      return buffer.toString();
    }
  
    /// The value of `consumeNewlines` is not relevant for this class.
    void _whitespace() {
      whitespace(consumeNewlines: true);
    }
  }
  