dynamic processTerm()

in lib/parser.dart [2225:2398]


  dynamic /* Expression | List<Expression> | ... */ processTerm(
      [bool ieFilter = false]) {
    var start = _peekToken.span;
    Token? t; // token for term's value
    dynamic value; // value of term (numeric values)

    var unary = '';
    switch (_peek()) {
      case TokenKind.HASH:
        _eat(TokenKind.HASH);
        if (!_anyWhiteSpaceBeforePeekToken(TokenKind.HASH)) {
          String? hexText;
          if (_peekKind(TokenKind.INTEGER)) {
            var hexText1 = _peekToken.text;
            _next();
            // Append identifier only if there's no delimiting whitespace.
            if (_peekIdentifier() && _previousToken!.end == _peekToken.start) {
              hexText = '$hexText1${identifier().name}';
            } else {
              hexText = hexText1;
            }
          } else if (_peekIdentifier()) {
            hexText = identifier().name;
          }
          if (hexText != null) {
            return _parseHex(hexText, _makeSpan(start));
          }
        }

        if (isChecked) {
          _warning('Expected hex number', _makeSpan(start));
        }
        // Construct the bad hex value with a #<space>number.
        return _parseHex(' ${processTerm().text}', _makeSpan(start));
      case TokenKind.INTEGER:
        t = _next();
        value = int.parse('$unary${t.text}');
        break;
      case TokenKind.DOUBLE:
        t = _next();
        value = double.parse('$unary${t.text}');
        break;
      case TokenKind.SINGLE_QUOTE:
        value = processQuotedString(false);
        value = "'${_escapeString(value as String, single: true)}'";
        return LiteralTerm(value, value, _makeSpan(start));
      case TokenKind.DOUBLE_QUOTE:
        value = processQuotedString(false);
        value = '"${_escapeString(value as String)}"';
        return LiteralTerm(value, value, _makeSpan(start));
      case TokenKind.LPAREN:
        _next();

        var group = GroupTerm(_makeSpan(start));

        dynamic /* Expression | List<Expression> | ... */ term;
        do {
          term = processTerm();
          if (term != null && term is LiteralTerm) {
            group.add(term);
          }
        } while (term != null &&
            !_maybeEat(TokenKind.RPAREN) &&
            !isPrematureEndOfFile());

        return group;
      case TokenKind.LBRACK:
        _next();

        var term = processTerm();
        if (!(term is NumberTerm)) {
          _error('Expecting a positive number', _makeSpan(start));
        }

        _eat(TokenKind.RBRACK);

        return ItemTerm(term.value, term.text as String, _makeSpan(start));
      case TokenKind.IDENTIFIER:
        var nameValue = identifier(); // Snarf up the ident we'll remap, maybe.

        if (!ieFilter && _maybeEat(TokenKind.LPAREN)) {
          var calc = processCalc(nameValue);
          if (calc != null) return calc;
          // FUNCTION
          return processFunction(nameValue);
        }
        if (ieFilter) {
          if (_maybeEat(TokenKind.COLON) &&
              nameValue.name.toLowerCase() == 'progid') {
            // IE filter:progid:
            return processIEFilter(start);
          } else {
            // Handle filter:<name> where name is any filter e.g., alpha,
            // chroma, Wave, blur, etc.
            return processIEFilter(start);
          }
        }

        // TODO(terry): Need to have a list of known identifiers today only
        //              'from' is special.
        if (nameValue.name == 'from') {
          return LiteralTerm(nameValue, nameValue.name, _makeSpan(start));
        }

        // What kind of identifier is it, named color?
        var colorEntry = TokenKind.matchColorName(nameValue.name);
        if (colorEntry == null) {
          if (isChecked) {
            var propName = nameValue.name;
            var errMsg = TokenKind.isPredefinedName(propName)
                ? 'Improper use of property value $propName'
                : 'Unknown property value $propName';
            _warning(errMsg, _makeSpan(start));
          }
          return LiteralTerm(nameValue, nameValue.name, _makeSpan(start));
        }

        // Yes, process the color as an RGB value.
        var rgbColor =
            TokenKind.decimalToHex(TokenKind.colorValue(colorEntry), 6);
        return _parseHex(rgbColor, _makeSpan(start));
      case TokenKind.UNICODE_RANGE:
        String? first;
        String? second;
        int firstNumber;
        int secondNumber;
        _eat(TokenKind.UNICODE_RANGE, unicodeRange: true);
        if (_maybeEat(TokenKind.HEX_INTEGER, unicodeRange: true)) {
          first = _previousToken!.text;
          firstNumber = int.parse('0x$first');
          if (firstNumber > MAX_UNICODE) {
            _error('unicode range must be less than 10FFFF', _makeSpan(start));
          }
          if (_maybeEat(TokenKind.MINUS, unicodeRange: true)) {
            if (_maybeEat(TokenKind.HEX_INTEGER, unicodeRange: true)) {
              second = _previousToken!.text;
              secondNumber = int.parse('0x$second');
              if (secondNumber > MAX_UNICODE) {
                _error(
                    'unicode range must be less than 10FFFF', _makeSpan(start));
              }
              if (firstNumber > secondNumber) {
                _error('unicode first range can not be greater than last',
                    _makeSpan(start));
              }
            }
          }
        } else if (_maybeEat(TokenKind.HEX_RANGE, unicodeRange: true)) {
          first = _previousToken!.text;
        }

        return UnicodeRangeTerm(first, second, _makeSpan(start));
      case TokenKind.AT:
        if (messages.options.lessSupport) {
          _next();

          var expr = processExpr();
          if (isChecked && expr.expressions.length > 1) {
            _error('only @name for Less syntax', _peekToken.span);
          }

          var param = expr.expressions[0];
          var varUsage =
              VarUsage((param as LiteralTerm).text, [], _makeSpan(start));
          expr.expressions[0] = varUsage;
          return expr.expressions;
        }
        break;
    }

    return t != null
        ? processDimension(t, value as Object, _makeSpan(start))
        : null;
  }