class TokenPredicate extends Expression.Arg.Pred<ChunkTaggedToken> {
  private final Predicate<ChunkTaggedToken> predicate;

  TokenPredicate(String description, boolean caseSensitive) {
    super(description);
    predicate = compile(description, caseSensitive);
  }

  private Predicate<ChunkTaggedToken> compile(String description, boolean caseSensitive) {<FILL_FUNCTION_BODY>}

  private static String unquote(String s) {
    return s.startsWith("'") && s.endsWith("'") ? s.substring(1, s.length() - 1) : s;
  }

  @Override
  public boolean apply(ChunkTaggedToken analyzedToken) {
    return predicate.test(analyzedToken);
  }
}

    String[] parts = description.split("=");
    String exprType;
    String exprValue;
    if (parts.length == 1) {
      exprType = "string";
      exprValue = unquote(parts[0]);
    } else if (parts.length == 2) {
      exprType = parts[0];
      exprValue = unquote(parts[1]);
    } else {
      throw new RuntimeException("Could not parse expression: " + getDescription());
    }

    switch (exprType) {
      case "string":
      case "regex":
      case "regexCS":
        StringMatcher matcher = StringMatcher.create(exprValue, !"string".equals(exprType), caseSensitive || "regexCS".equals(exprType));
        return analyzedToken -> matcher.matches(analyzedToken.getToken());

      case "chunk":
        StringMatcher chunkPattern = StringMatcher.regexp(exprValue);
        return analyzedToken -> {
          for (ChunkTag chunkTag : analyzedToken.getChunkTags()) {
            if (chunkPattern.matches(chunkTag.getChunkTag())) {
              return true;
            }
          }
          return false;
        };

      case "pos":
        return analyzedToken -> {
          AnalyzedTokenReadings readings = analyzedToken.getReadings();
          if (readings != null) {
            for (AnalyzedToken token : readings) {
              if (token.getPOSTag() != null && token.getPOSTag().contains(exprValue)) {
                return true;
              }
            }
          }
          return false;
        };

      case "posre":
      case "posregex":
        StringMatcher posPattern = StringMatcher.regexp(exprValue);
        return analyzedToken -> {
          AnalyzedTokenReadings readings = analyzedToken.getReadings();
          if (readings != null) {
            for (AnalyzedToken token : readings) {
              if (token.getPOSTag() != null && posPattern.matches(token.getPOSTag())) {
                return true;
              }
            }
          }
          return false;
        };

      default:
        throw new RuntimeException("Expression type not supported: '" + exprType + "'");
    }

  
<no_super_class>